[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

 

posted @ 2021-10-29 13:58  PYWBKTDA  阅读(94)  评论(0编辑  收藏  举报