1. 程式人生 > 其它 >[gym102412D]The Jump from Height of Self-importance to Height of IQ Level

[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)$,可以通過

 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 }
View Code