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]
用的非旋转treap
这种treap只有两种操作:
merge(root1,root2)和split(root,k)
分别表示合并两颗treap和分割一个treap的前k个节点
其他操作都通过这两个实现
这样不用旋转,就可以持久化
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 struct Treap 7 { 8 Treap *l,*r; 9 int val,size,lev; 10 }S[200001],*pos=S,*root; 11 int n; 12 typedef pair<Treap*,Treap*> Droot; 13 void NewNode(Treap* &r,int val) 14 { 15 r=++pos; 16 r->val=val; 17 r->lev=rand(); 18 r->size=1; 19 r->l=r->r=0; 20 } 21 int getsize(Treap* x) 22 { 23 if (!x) return 0; 24 else return x->size; 25 } 26 void updata(Treap* x) 27 { 28 x->size=1; 29 if (x->l) x->size+=x->l->size; 30 if (x->r) x->size+=x->r->size; 31 } 32 Treap *merge(Treap *A,Treap *B) 33 { 34 if (!A) return B; 35 if (!B) return A; 36 if (A->lev<B->lev) 37 { 38 A->r=merge(A->r,B); 39 updata(A); 40 return A; 41 } 42 else 43 { 44 B->l=merge(A,B->l); 45 updata(B); 46 return B; 47 } 48 } 49 Droot split(Treap *x,int k) 50 { 51 if (!x) return Droot(0,0); 52 Droot y; 53 if (getsize(x->l)>=k) 54 { 55 y=split(x->l,k); 56 x->l=y.second; 57 updata(x); 58 y.second=x; 59 } 60 else 61 { 62 y=split(x->r,k-getsize(x->l)-1); 63 x->r=y.first; 64 updata(x); 65 y.first=x; 66 } 67 return y; 68 } 69 int findkth(int k) 70 { 71 Droot x=split(root,k-1); 72 Droot y=split(x.second,1); 73 Treap* ans=y.first; 74 root=merge(merge(x.first,ans),y.second); 75 if (ans==0) return 0; 76 return ans->val; 77 } 78 int getkth(Treap* x,int val) 79 { 80 if (x==0) return 0; 81 if (val<=x->val) 82 return getkth(x->l,val); 83 else return getkth(x->r,val)+getsize(x->l)+1; 84 } 85 void insert(int val) 86 { 87 int k=getkth(root,val); 88 Droot x=split(root,k); 89 Treap *a; 90 NewNode(a,val); 91 root=merge(merge(x.first,a),x.second); 92 } 93 int del(int val) 94 { 95 int k=getkth(root,val); 96 Droot x=split(root,k); 97 Droot y=split(x.second,1); 98 Treap* ans=y.first; 99 root=merge(x.first,y.second); 100 } 101 int main() 102 {int opt,x; 103 cin>>n; 104 while (n--) 105 { 106 scanf("%d%d",&opt,&x); 107 if (opt==1) 108 insert(x); 109 else if (opt==2) 110 del(x); 111 else if (opt==3) 112 printf("%d\n",getkth(root,x)+1); 113 else if (opt==4) 114 printf("%d\n",findkth(x)); 115 else if (opt==5) 116 printf("%d\n",findkth(getkth(root,x))); 117 else if (opt==6) 118 printf("%d\n",findkth(getkth(root,x+1)+1)); 119 } 120 }