bzoj 3224: Tyvj 1728 普通平衡树
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
这是平衡树的入门题了,可以有很多种写法:
1.权值线段树
2.treap
3. splay
4.替罪羊树
5.fhq treap (可持久化treap)
附录: 可持久化平衡树代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=100000+10; 4 int n,val[N],key[N],ch[N][2],sz[N],root,rb[N],top; 5 void update(int x){ 6 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 7 } 8 int mr(int k){ 9 int x=rb[top--];val[x]=k;sz[x]=1;ch[x][0]=ch[x][1]=0;key[x]=rand(); return x; 10 } 11 int getkth(int x,int k){ 12 while (x){ 13 if(sz[ch[x][0]]>=k) x=ch[x][0]; 14 else if(sz[ch[x][0]]+1==k) return val[x]; 15 else k-=sz[ch[x][0]]+1,x=ch[x][1]; 16 } 17 } 18 void split(int now,int k,int &x,int &y){ 19 if(!now) x=y=0; 20 else { 21 if(val[now]<=k) 22 x=now,split(ch[now][1],k,ch[now][1],y); 23 else 24 y=now,split(ch[now][0],k,x,ch[now][0]); 25 update(now); 26 } 27 } 28 int merge(int x,int y){ 29 if(!x || !y) return x+y; 30 if(key[x]<key[y]) { 31 ch[x][1]=merge(ch[x][1],y); 32 update(x); 33 return x; 34 }else { 35 ch[y][0]=merge(x,ch[y][0]); 36 update(y); 37 return y; 38 } 39 } 40 int main(){ 41 int x,y,z,opt,k; 42 scanf("%d",&n); 43 for(int i=1;i<=n;i++) rb[i]=n-i+1; 44 top=n; 45 while (n--){ 46 scanf("%d%d",&opt,&k); 47 if(opt==1){ 48 split(root,k,x,y); 49 root=merge(merge(x,mr(k)),y); 50 } 51 if(opt==2){ 52 split(root,k,x,y); 53 split(x,k-1,x,z); 54 rb[++top]=z; 55 z=merge(ch[z][0],ch[z][1]); 56 root=merge(merge(x,z),y); 57 } 58 if(opt==3){ 59 split(root,k-1,x,y); 60 printf("%d\n",sz[x]+1); 61 root=merge(x,y); 62 } 63 if(opt==4){ 64 printf("%d\n",getkth(root,k)); 65 } 66 if(opt==5){ 67 split(root,k-1,x,y); 68 printf("%d\n",getkth(x,sz[x])); 69 root=merge(x,y); 70 } 71 if(opt==6){ 72 split(root,k,x,y); 73 printf("%d\n",getkth(y,1)); 74 root=merge(x,y); 75 } 76 } 77 return 0; 78 }