题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 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
2.每个数的数据范围: [-{10}^7, {10}^7]
--------------------------------------------------------------------------------------
刚学的,不用旋转的TREAP
好写,主要就是split和merge两个操作。
可以实现可持久化。
可以实现区间操作。
据说,比splay要慢
--------------------------------------------------------------------------------------
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+5; 4 const int inf=1e9; 5 struct node 6 { 7 int ch[2],val,rd,siz; 8 }tr[maxn]; 9 int n,m,l,r; 10 int tot,root; 11 int newnode(int v) 12 { 13 ++tot; 14 tr[tot].val=v; 15 tr[tot].rd=rand(); 16 tr[tot].siz=1; 17 tr[tot].ch[0]=tr[tot].ch[1]=0; 18 return tot; 19 } 20 void update(int x) 21 { 22 tr[x].siz=tr[tr[x].ch[0]].siz+tr[tr[x].ch[1]].siz+1; 23 } 24 int merge(int a,int b) 25 { 26 if(a*b==0)return a+b; 27 if(tr[a].rd<tr[b].rd) 28 { 29 tr[a].ch[1]=merge(tr[a].ch[1],b); 30 update(a); 31 return a; 32 } 33 else 34 { 35 tr[b].ch[0]=merge(a,tr[b].ch[0]); 36 update(b); 37 return b; 38 } 39 } 40 void split(int cur,int k,int &x,int &y) 41 { 42 if(!cur)x=y=0; 43 else 44 { 45 if(tr[cur].val<=k) 46 { 47 x=cur; 48 split(tr[cur].ch[1],k,tr[cur].ch[1],y); 49 } 50 else 51 { 52 y=cur; 53 split(tr[cur].ch[0],k,x,tr[cur].ch[0]); 54 } 55 update(cur); 56 } 57 } 58 void insert(int v) 59 { 60 int x,y; 61 split(root,v,x,y); 62 root=merge(merge(x,newnode(v)),y); 63 } 64 void del(int v) 65 { 66 int x,y,z; 67 split(root,v,x,z); 68 split(x,v-1,x,y); 69 y=merge(tr[y].ch[0],tr[y].ch[1]); 70 root=merge(merge(x,y),z); 71 } 72 void findrank(int v) 73 { 74 int x,y; 75 split(root,v-1,x,y); 76 printf("%d ",tr[x].siz+1); 77 root=merge(x,y); 78 } 79 int kth(int now,int k) 80 { 81 int cur=now; 82 while(cur) 83 { 84 if(tr[tr[cur].ch[0]].siz+1==k)return tr[cur].val; 85 else if(tr[tr[cur].ch[0]].siz>=k)cur=tr[cur].ch[0]; 86 else 87 { 88 k-=tr[tr[cur].ch[0]].siz+1; 89 cur=tr[cur].ch[1]; 90 } 91 } 92 return -inf; 93 } 94 void pre(int v) 95 { 96 int x,y; 97 split(root,v-1,x,y); 98 printf("%d ",kth(x,tr[x].siz)); 99 root=merge(x,y); 100 } 101 void suc(int v) 102 { 103 int x,y; 104 split(root,v,x,y); 105 printf("%d ",kth(y,1)); 106 root=merge(x,y); 107 } 108 int main() 109 { 110 srand((unsigned)time(NULL)); 111 int n,op,v; 112 scanf("%d",&n); 113 while(n--) 114 { 115 scanf("%d%d",&op,&v); 116 switch(op) 117 { 118 case 1:insert(v);break; 119 case 2:del(v);break; 120 case 3:findrank(v);break; 121 case 4:printf("%d ",kth(root,v));break; 122 case 5:pre(v);break; 123 case 6:suc(v);break; 124 default:break; 125 } 126 } 127 return 0; 128 }