[luogu 3369]普通平衡树(fhq_treap)
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
-
插入x数
-
删除x数(若有多个相同的数,因只删除一个)
-
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
-
查询排名为x的数
-
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1≤opt≤6 1 \leq opt \leq 6 1≤opt≤6 )
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入样例#1: 复制
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
输出样例#1: 复制
106465 84185 492737
说明
时空限制:1000ms,128M
1.n的数据范围: n≤100000 n \leq 100000 n≤100000
2.每个数的数据范围: $[-{10}^7, {10}^7]$
题解:
模板题,用的是fhq_treap。
1 //Never forget why you start 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<algorithm> 8 #include<ctime> 9 #define ll(x) tre[x].child[0] 10 #define rr(x) tre[x].child[1] 11 #define son(x,t) tre[x].child[t] 12 using namespace std; 13 int n,m,cnt,root; 14 struct Treap{ 15 int child[2],x,size,rev; 16 }tre[100005]; 17 void push_up(int root){ 18 tre[root].size=tre[ll(root)].size+tre[rr(root)].size+1; 19 } 20 int newnode(int x){ 21 cnt++; 22 tre[cnt].size=1; 23 tre[cnt].rev=rand(); 24 tre[cnt].x=x; 25 return cnt; 26 } 27 void split(int now,int k,int &x,int &y){ 28 if(!now)x=y=0; 29 else{ 30 if(tre[now].x<=k) 31 x=now,split(rr(now),k,rr(now),y); 32 else 33 y=now,split(ll(now),k,x,ll(now)); 34 push_up(now); 35 } 36 } 37 int merge(int x,int y){ 38 if(!x||!y)return x+y; 39 if(tre[x].rev<tre[y].rev){ 40 rr(x)=merge(rr(x),y); 41 push_up(x); 42 return x; 43 } 44 else{ 45 ll(y)=merge(x,ll(y)); 46 push_up(y); 47 return y; 48 } 49 } 50 int find(int root,int k){ 51 int y=tre[ll(root)].size; 52 if(y+1==k)return root; 53 else if(y>=k)return find(ll(root),k); 54 else find(rr(root),k-y-1); 55 } 56 int main(){ 57 int i,j,a,b,c; 58 srand(time(0)); 59 scanf("%d",&n); 60 while(n--){ 61 scanf("%d%d",&i,&j); 62 if(i==1){ 63 split(root,j,a,b); 64 root=merge(merge(a,newnode(j)),b); 65 } 66 if(i==2){ 67 split(root,j,a,c); 68 split(a,j-1,a,b); 69 b=merge(ll(b),rr(b)); 70 root=merge(merge(a,b),c); 71 } 72 if(i==3){ 73 split(root,j-1,a,b); 74 printf("%d\n",tre[a].size+1); 75 root=merge(a,b); 76 } 77 if(i==4){ 78 printf("%d\n",tre[find(root,j)].x); 79 } 80 if(i==5){ 81 split(root,j-1,a,b); 82 printf("%d\n",tre[find(a,tre[a].size)].x); 83 root=merge(a,b); 84 } 85 if(i==6){ 86 split(root,j,a,b); 87 printf("%d\n",tre[find(b,1)].x); 88 root=merge(a,b); 89 } 90 } 91 return 0; 92 }