[gym102412D]The Jump from Height of Self-importance to Height of IQ Level
考虑使用平衡树维护该序列,操作显然可以用fhq treap的分裂+合并来实现
进一步的,问题即变为维护哪些信息来支持push up的操作(并判定是否存在$a_{i}<a_{j}<a_{k}$),容易想到去维护区间最大值/最小值、最大的$a_{i}$/最小的$a_{j}$满足存在$a_{i}<a_{j}$、内部是否存在$a_{i}<a_{j}<a_{k}$
第一和三个信息都可以轻松的合并,而第二个信息合并时要找到左侧右侧最大值的前驱,显然并不能维护
若已经存在$a_{i}<a_{j}<a_{k}$时,该信息可以不维护;若不存在$a_{i}<a_{j}<a_{k}$时,左侧比右侧最大值小的数必然构成一个递减序列,其中最大的(前驱)即是最靠左的,以此查询即可
单次合并为$o(\log n)$,那么平衡树的复杂度即为$o(\log^{2}n)$
时间复杂度为$o(n\log^{2}n+q\log^{2}n)$,可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 120005 4 int n,m,rt,l,r,x,val[N],sz[N],rnd[N],mx[N],mn[N],vis[N],Mx[N],Mn[N],ch[N][2]; 5 int query_pre(int k,int x){ 6 if (!k)return 0; 7 if (mn[ch[k][0]]<x)return query_pre(ch[k][0],x); 8 if (val[k]<x)return val[k]; 9 return query_pre(ch[k][1],x); 10 } 11 int query_nex(int k,int x){ 12 if (!k)return n+1; 13 if (mx[ch[k][1]]>x)return query_nex(ch[k][1],x); 14 if (val[k]>x)return val[k]; 15 return query_nex(ch[k][0],x); 16 } 17 void up(int k){ 18 sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1; 19 mx[k]=max(max(mx[ch[k][0]],val[k]),mx[ch[k][1]]); 20 mn[k]=min(min(mn[ch[k][0]],val[k]),mn[ch[k][1]]); 21 vis[k]=(vis[ch[k][0]]|vis[ch[k][1]]); 22 vis[k]|=(Mn[ch[k][0]]<max(val[k],mx[ch[k][1]])); 23 vis[k]|=(min(val[k],mn[ch[k][0]])<Mx[ch[k][1]]); 24 vis[k]|=((mn[ch[k][0]]<val[k])&&(val[k]<mx[ch[k][1]])); 25 if (vis[k])return; 26 Mx[k]=max(Mx[ch[k][0]],Mx[ch[k][1]]); 27 Mx[k]=max(Mx[k],query_pre(ch[k][0],max(val[k],mx[ch[k][1]]))); 28 if (val[k]<mx[ch[k][1]])Mx[k]=max(Mx[k],val[k]); 29 Mn[k]=min(Mn[ch[k][0]],Mn[ch[k][1]]); 30 Mn[k]=min(Mn[k],query_nex(ch[k][1],min(val[k],mn[ch[k][0]]))); 31 if (mn[ch[k][0]]<val[k])Mn[k]=min(Mn[k],val[k]); 32 } 33 int merge(int x,int y){ 34 if ((!x)||(!y))return x+y; 35 int k; 36 if (rnd[x]<rnd[y]){ 37 k=x; 38 ch[k][1]=merge(ch[k][1],y); 39 } 40 else{ 41 k=y; 42 ch[k][0]=merge(x,ch[k][0]); 43 } 44 up(k); 45 return k; 46 } 47 void split(int k,int &x,int &y,int z){ 48 if (!k){ 49 x=y=0; 50 return; 51 } 52 if (z<=sz[ch[k][0]]){ 53 y=k; 54 split(ch[k][0],x,ch[y][0],z); 55 up(y); 56 } 57 else{ 58 x=k; 59 split(ch[k][1],ch[x][1],y,z-sz[ch[k][0]]-1); 60 up(x); 61 } 62 } 63 int main(){ 64 srand(time(0)); 65 scanf("%d",&n); 66 memset(mn,0x3f,sizeof(mn)); 67 memset(Mn,0x3f,sizeof(Mn)); 68 for(int i=1;i<=n;i++){ 69 scanf("%d",&val[i]); 70 sz[i]=1,rnd[i]=rand(),mx[i]=mn[i]=val[i]; 71 rt=merge(rt,i); 72 } 73 scanf("%d",&m); 74 for(int i=1;i<=m;i++){ 75 scanf("%d%d%d",&l,&r,&x); 76 int rtl,rtr,rt1,rt2; 77 split(rt,rtl,rt,l-1),split(rt,rt,rtr,r-l+1); 78 split(rt,rt1,rt2,(r-l+1)-x),rt=merge(rt2,rt1); 79 rt=merge(merge(rtl,rt),rtr); 80 if (vis[rt])printf("YES\n"); 81 else printf("NO\n"); 82 } 83 return 0; 84 }