LOJ104 普通平衡树
题目描述
这是一道模板题。
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 x 数;
- 删除 x 数(若有多个相同的数,因只删除一个);
- 查询 x 数的排名(若有多个相同的数,因输出最小的排名);
- 查询排名为 x 的数;
- 求 x 的前趋(前趋定义为小于 x,且最大的数);
- 求 x 的后继(后继定义为大于 x,且最小的数)。
输入格式
第一行为 n,表示操作的个数,下面 n 行每行有两个数 opt 和 x, 表示操作的序号(1<=opt<=6)。
输出格式
对于操作 3、4、5、6 每行输出一个数,表示对应答案。
样例
样例输入
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
样例输出
106465
84185
492737
数据范围与提示
1<=n<=105,-107<=x<=107
___________________________________________________________________________
fhq_treap模板
___________________________________________________________________________
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 struct node 5 { 6 int val,lc,rc,siz,rd; 7 }tr[maxn]; 8 int cnt,root,n; 9 int newnode(int v) 10 { 11 ++cnt; 12 tr[cnt].val=v; 13 tr[cnt].siz=1; 14 tr[cnt].rd=rand(); 15 tr[cnt].lc=tr[cnt].rc=0; 16 return cnt; 17 } 18 void update(int cur) 19 { 20 tr[cur].siz=tr[tr[cur].lc].siz+tr[tr[cur].rc].siz+1; 21 } 22 int merge(int x,int y) 23 { 24 if(x*y==0)return x+y; 25 if(tr[x].rd<tr[y].rd) 26 { 27 tr[x].rc=merge(tr[x].rc,y); 28 update(x); 29 return x; 30 } 31 else 32 { 33 tr[y].lc=merge(x,tr[y].lc); 34 update(y); 35 return y; 36 } 37 } 38 void split(int cur,int v,int &x,int &y) 39 { 40 if(!cur)x=y=0; 41 else 42 { 43 if(tr[tr[cur].lc].siz+1<=v) 44 { 45 x=cur; 46 split(tr[cur].rc,v-tr[tr[cur].lc].siz-1,tr[cur].rc,y); 47 update(cur); 48 } 49 else 50 { 51 y=cur; 52 split(tr[cur].lc,v,x,tr[cur].lc); 53 update(cur); 54 } 55 } 56 } 57 void splitv(int cur,int v,int &x,int &y) 58 { 59 if(!cur)x=y=0; 60 else 61 { 62 if(tr[cur].val<=v) 63 { 64 x=cur; 65 splitv(tr[cur].rc,v,tr[cur].rc,y); 66 update(cur); 67 } 68 else 69 { 70 y=cur; 71 splitv(tr[cur].lc,v,x,tr[cur].lc); 72 update(cur); 73 } 74 } 75 } 76 void insert(int v) 77 { 78 int x,y; 79 splitv(root,v,x,y); 80 root=merge(merge(x,newnode(v)),y); 81 } 82 void del(int v) 83 { 84 int x,y,z; 85 splitv(root,v,x,z); 86 splitv(x,v-1,x,y); 87 y=merge(tr[y].lc,tr[y].rc); 88 root=merge(merge(x,y),z); 89 } 90 void find(int v) 91 { 92 int x,y; 93 splitv(root, v-1,x,y); 94 printf("%d\n",tr[x].siz+1); 95 root=merge(x,y); 96 } 97 void kth(int now,int v) 98 { 99 int cur=now; 100 if(v>tr[now].siz || v<1)return ; 101 while(cur) 102 { 103 if(tr[tr[cur].lc].siz+1==v) 104 { 105 printf("%d\n",tr[cur].val); 106 return ; 107 } 108 else if(tr[tr[cur].lc].siz >= v)cur=tr[cur].lc; 109 else 110 { 111 v-=tr[tr[cur].lc].siz+1; 112 cur=tr[cur].rc; 113 } 114 } 115 } 116 void pre(int v) 117 { 118 int x,y,z; 119 splitv(root,v-1,x,y); 120 kth(x,tr[x].siz); 121 root=merge(x,y); 122 } 123 void next(int v) 124 { 125 int x,y,z; 126 splitv(root,v,x,y); 127 kth(y,1); 128 root=merge(x,y); 129 } 130 int main() 131 { 132 scanf("%d",&n); 133 for(int op,x,i=0;i<n;++i) 134 { 135 scanf("%d%d",&op,&x); 136 if(op==1)insert(x); 137 else if(op==2)del(x); 138 else if(op==3)find(x); 139 else if(op==4)kth(root,x); 140 else if(op==5)pre(x); 141 else next(x); 142 } 143 return 0; 144 }