#include<bits/stdc++.h>
using namespace std;
//思路:
//1.找到tl,tr
//2.找到中间的位置u,并得到u能延伸的区间[l,r]
//3.判断tl,tr,l,r关系
//各个值的意义
//int a[]原值,b[]离散,a[]离散化后的值
//int l[i],r[i]储存位置i的值x可以作为区间最小值,所能延申的最大距离 ,即单调栈 栈内从1->n递增
//int mxl[i],mxr[i],分别为从左右两边到i的最大值
//vector<int>g[i] 值i出现的各个位置
//步骤:
//step1.离散化
//step2.for(x=1->tot) 挨个判断 值x 是否可以
//step3.tl = g[x][0], tr = g[x][g[x].size()-1]
//需满足:mxl[tl]=x && mxr[tr]=x
//step4.for(j=1->g[x].size()-2) 挨个判断 第j个出现的x是否可以 u=g[x][j],u为位置
//step5.用单调栈预处理得到u作为最小值可以延伸的区间[l,r] l[i],r[i]
//step6.判断tl,tr,l,r关系
//左右一样,此处只讨论左边的情况
//1.l<tl 可,第一个区间范围:[1,tl]
//2.l>=tl && mxl[l-1]=x 可,第一个区间范围:[1,l-1]
const int N = 2e5+23 ;
int a[N],b[N] ;
int mxl[N],mxr[N] ;
int l[N],r[N] ;
vector<int>g[N] ;
stack<int>st ;
int main()
{
int t ;
scanf("%d",&t) ;
while(t--)
{
//step1.输入+离散
int n ;
scanf("%d",&n) ;
for(int i = 1 ; i <= n ; i++)
{
scanf("%d",&a[i]) ;
b[i-1] = a[i] ;
}
sort(b,b+n) ;
int tot = unique(b,b+n)-b ;
while(!st.empty()) st.pop() ;
int top ;
mxl[0] = 0 ;
for(int i = 1 ; i <= n ; i++)
{
a[i] = lower_bound(b,b+tot,a[i])-b+1 ;
//step2.预处理mxl[] ,g[]
mxl[i] = max(mxl[i-1],a[i]) ;
g[a[i]].push_back(i) ;
//step3.预处理单调栈l[]
while(!st.empty() && a[st.top()]>=a[i]) st.pop() ;//保证单调栈单调递减 (栈内增)
if(st.empty()) l[i] = 1 ;
else l[i] = st.top()+1 ;
st.push(i) ;
}
mxr[n+1] = 0 ;
while(!st.empty()) st.pop() ;
for(int i = n ; i >= 1 ; i--)
{
//step2.预处理mxr[]
mxr[i] = max(mxr[i+1],a[i]) ;
//step3.预处理单调栈r[]
while(!st.empty() && a[st.top()]>=a[i]) st.pop() ;//保证单调栈单调递减 (栈内增)
if(st.empty()) r[i] = n ;
else r[i] = st.top()-1 ;
st.push(i) ;
}
// for(int i = 1 ; i <= n ; i++) printf("%d ",a[i]) ;
// puts("") ;
// for(int i = 1 ; i <= n ; i++) printf("%d ",l[i]) ;
// puts("") ;
// for(int i = 1 ; i <= n ; i++) printf("%d ",r[i]) ;
// puts("") ;
//step4 选x
int flag = 0,ans1,ans2,ans3 ;
for(int i = 1 ; i <= tot ; i++)
{
int sz = g[i].size() ;
int tl = g[i][0] , tr = g[i][sz-1] ;
// printf("tl=%d tr=%d i=%d\n",tl,tr,i) ;
if(mxl[tl]!=i || mxr[tr]!=i || sz<3) continue ;
for(int j = 1 ; j <= sz-2 ; j++)
{
int u = g[i][j] ;//u为值i出现的位置
if((l[u]<=tl||(l[u]>tl && mxl[l[u]-1]==i)) && (r[u]>=tr||(r[u]<tr && mxr[r[u]+1]==i)))
{
// printf("l=%d r=%d u=%d\n",l[u],r[u],u) ;
ans1 = max(tl,l[u]-1) ;
ans2 = min(tr-1,r[u])-ans1 ;
ans3 = n-ans2-ans1 ;
flag = 1 ;
break ;
}
}
if(flag) break ;
}
if(flag)
{
puts("YES") ;
printf("%d %d %d\n",ans1,ans2,ans3) ;
}
else puts("NO") ;
for(int i = 1 ; i <= tot ; i++) g[i].clear() ;
}
return 0 ;
}
CodeForces - 1454F
最新推荐文章于 2024-08-07 03:42:49 发布