bzoj3196: Tyvj 1730 二逼平衡树

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #define maxn 50005
  7 #define maxk 2000005
  8 #define inf 100000000
  9 using namespace std;
 10 
 11 int n,m,tot,sum,Ans,root[maxn<<2],val[maxk],times[maxk],size[maxk],fa[maxk],son[maxk][2],a[maxn];
 12 struct Tsegment{
 13     void clear(){
 14         tot=0,memset(val,0,sizeof(val));
 15         memset(root,0,sizeof(0));
 16         memset(son,0,sizeof(son));
 17         memset(fa,0,sizeof(fa));
 18         memset(times,0,sizeof(times));
 19         memset(size,0,sizeof(size));
 20     }
 21     int which(int x){return son[fa[x]][1]==x;}
 22     void update(int x){
 23         size[x]=size[son[x][0]]+size[son[x][1]]+times[x];
 24     }
 25     void rotata(int x){
 26         int y=fa[x],d=which(x),dd=which(y);
 27         if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y];
 28         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
 29         fa[y]=x,son[x][d^1]=y,update(y);
 30     }
 31     void splay(int x,int goal,int op){
 32         while (fa[x]!=goal){
 33             if (fa[fa[x]]==goal) rotata(x);
 34             else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
 35             else rotata(x),rotata(x);
 36         }
 37         update(x); if (goal==0) root[op]=x;
 38     }
 39     void insert(int k,int x){
 40         int y=root[k]; bool bo;
 41         if (y==0){
 42             root[k]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=son[tot][0]=son[tot][1]=0;
 43             return;
 44         }
 45         for (;;){
 46             bo=0;
 47             if (val[y]==x) times[y]++,size[y]++,bo=1,splay(y,0,k);
 48             else if (x<val[y]){
 49                 if (!son[y][0]) son[y][0]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=y,bo=1,splay(tot,0,k);
 50                 else y=son[y][0];
 51             }else{
 52                 if (!son[y][1]) son[y][1]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=y,bo=1,splay(tot,0,k);
 53                 else y=son[y][1];
 54             }
 55             if (bo==1) break;
 56         }
 57     }
 58     void query(int k,int x){
 59         int y=root[k]; if (y==0) return;
 60         for (;;){
 61             if (y==0) break;
 62             if (val[y]==x){
 63                 sum+=size[son[y][0]];
 64                 break;
 65             }else if (val[y]<x){
 66                 sum+=(size[son[y][0]]+times[y]);
 67                 y=son[y][1];
 68             }else y=son[y][0];
 69         }
 70     }
 71     int prep(int k,int x){
 72         splay(x,0,k);
 73         int y=son[x][0];
 74         while (son[y][1]) y=son[y][1];
 75         return y;
 76     }
 77     void DLT(int k,int x){
 78         int y=prep(k,x),z;
 79         if (y==0){
 80             splay(x,0,k);
 81             z=son[x][1];
 82             fa[z]=0,son[x][0]=son[x][1]=0,fa[x]=0,root[k]=z,times[x]=size[x]=0;
 83             splay(z,0,k);
 84         }else{
 85             splay(y,0,k),splay(x,y,k);
 86             z=son[x][1];
 87             fa[z]=y,son[y][1]=z,fa[x]=son[x][0]=son[x][1]=size[x]=times[x]=0;
 88             update(y);
 89         }
 90     }
 91     void dlt(int k,int x){
 92         int y=root[k]; if (y==0) return; bool bo;
 93         for (;;){
 94             bo=0;
 95             if (val[y]==x){
 96                 if (times[y]>1) times[y]--,size[y]--,bo=1,splay(y,0,k);
 97                 else{
 98                     times[y]--,size[y]--,bo=1,DLT(k,y);
 99                 }
100             }else if (x<val[y]) y=son[y][0];
101             else y=son[y][1];
102             if (bo==1) break;
103         }
104     }
105     void query4(int k,int x){
106         int y=root[k]; if (y==0) return;
107         for (;;){
108             if (y==0) break;
109             if (val[y]<x) Ans=max(Ans,val[y]),y=son[y][1];
110             else y=son[y][0];
111         }
112     }
113     void query5(int k,int x){
114         int y=root[k]; if (y==0) return;
115         for (;;){
116             if (y==0) break;
117             if (x<val[y]) Ans=min(Ans,val[y]),y=son[y][0];
118             else y=son[y][1];
119         }
120     }
121 }Splay;
122 struct date{
123     void insert(int k,int l,int r,int x){
124         Splay.insert(k,a[x]);
125         if (l==r) return;
126         int mid=(l+r)>>1;
127         if (x<=mid) insert(k*2,l,mid,x);
128         else insert(k*2+1,mid+1,r,x);
129     }
130     void query(int k,int l,int r,int x,int y,int z){
131         if (l>=x&&r<=y){
132             Splay.query(k,z);
133             return;
134         }int mid=(l+r)>>1;
135         if (x<=mid) query(k*2,l,mid,x,y,z);
136         if (y>mid) query(k*2+1,mid+1,r,x,y,z);
137     }
138     int check(int x,int y,int z){
139         sum=0,query(1,1,n,x,y,z);
140         return sum;
141     }
142     void dlt(int k,int l,int r,int x,int y){
143         Splay.dlt(k,y);
144         if (l==r) return;
145         int mid=(l+r)>>1;
146         if (x<=mid) dlt(k*2,l,mid,x,y);
147         else dlt(k*2+1,mid+1,r,x,y);
148     }
149     void query4(int k,int l,int r,int x,int y,int z){
150         if (l>=x&&r<=y){
151             Splay.query4(k,z);
152             return;
153         }int mid=(l+r)>>1;
154         if (x<=mid) query4(k*2,l,mid,x,y,z);
155         if (y>mid) query4(k*2+1,mid+1,r,x,y,z);
156     }
157     void query5(int k,int l,int r,int x,int y,int z){
158         if (l>=x&&r<=y){
159             Splay.query5(k,z);
160             return;
161         }int mid=(l+r)>>1;
162         if (x<=mid) query5(k*2,l,mid,x,y,z);
163         if (y>mid) query5(k*2+1,mid+1,r,x,y,z);
164     }
165 }Tree;
166 struct note{
167     void query1(int x,int y,int z){
168         sum=0,Tree.query(1,1,n,x,y,z);
169         printf("%d
",++sum);
170     }
171     void query2(int x,int y,int z){
172         int low=0,high=inf,mid,ans=0;
173         while (low<=high){
174             mid=(low+high)/2;
175             if (Tree.check(x,y,mid)+1<=z) ans=mid,low=mid+1;
176             else high=mid-1;
177         }
178         printf("%d
",ans);
179     }
180     void query3(int x,int y){
181         Tree.dlt(1,1,n,x,a[x]);
182         a[x]=y,Tree.insert(1,1,n,x);
183     }
184     void query4(int x,int y,int z){
185         Ans=0;
186         Tree.query4(1,1,n,x,y,z);
187         printf("%d
",Ans);
188     }
189     void query5(int x,int y,int z){
190         Ans=inf;
191         Tree.query5(1,1,n,x,y,z);
192         printf("%d
",Ans);
193     }
194 }Task;
195 
196 int main(){
197     int oppo,u,v,w;
198     scanf("%d%d",&n,&m);
199     Splay.clear();
200     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
201     for (int i=1;i<=n;i++) Tree.insert(1,1,n,i);
202     while (m--){
203          scanf("%d%d%d",&oppo,&u,&v);
204         if (oppo==1) scanf("%d",&w),Task.query1(u,v,w);
205         else if (oppo==2) scanf("%d",&w),Task.query2(u,v,w);
206         else if (oppo==3) Task.query3(u,v);
207          else if (oppo==4) scanf("%d",&w),Task.query4(u,v,w);
208         else scanf("%d",&w),Task.query5(u,v,w);
209     }
210     return 0;
211 }
View Code

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3196

题目大意:

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

序列长度为n,操作个数为m,n<=5*10^4,m<=5*10^4;

做法:对于区间最大值或区间最小值我们可以用线段树,对于整个序列第k小,求排名,求前驱,求后继,我们可以用splay,-->那么对于区间求排名,求第k小,求前驱,求后继,我们可以用树套树,线段树套splay,线段树维护区间位置,对于线段树的每个节点,我们维护一棵splay,维护这段区间中的权值。每加入一个点,需要增开logn的空间,故空间复杂度为(n+m)logn,操作1,3,4,5的时间复杂度均为log^2 n,操作2的时间复杂度为log^3 n;可以过此题。

对于操作1:我们在线段树上找相应的区间,在其splay上询问有多少个节点权值<它,最后把sum++,即为答案,脑补;

对于操作2:我们考虑二分答案,即转化为了操作1,若该答案的排名<=k,ans=mid,l=mid+1,否则r=mid-1,输出ans即可;

对于操作3:线段树中,将所有包含该位置的点原来的权值删去,并将新权值加入;

对于操作4:在每棵splay上查找即可(splay具有二分性质);

对于操作5:与操作4相似;

注意:线段树记录相应splay的根,每次将某个节点旋到所在splay树上的根是,记得更新线段树记录的根,以防出错。

具体细节见代码。

树套树,线段树套splay。

原文地址:https://www.cnblogs.com/OYzx/p/5538270.html