bzoj3224 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.每个数的数据范围:[-1e7,1e7]
数据如下http://pan.baidu.com/s/1jHMJwO2
正解:平衡树。
这题就是平衡树,各种平衡树都能写。。今天晚上学了学替罪羊树,我能说我调了一晚上的原因是因为insert的传址问题吗。。
替罪羊树:
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define N (100010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 int ch[N][2],cover[N],sz[N],val[N],del[N],st[N],Q,rt,top,tot; 23 const double alpha=0.75; 24 25 il int gi(){ 26 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 27 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 28 } 29 30 il void pushup(RG int x){ 31 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+(!del[x]); 32 cover[x]=cover[ch[x][0]]+cover[ch[x][1]]+1; return; 33 } 34 35 il void dfs(RG int x){ 36 if (ch[x][0]) dfs(ch[x][0]); 37 if (!del[x]) st[++top]=x; 38 if (ch[x][1]) dfs(ch[x][1]); 39 sz[x]=cover[x]=ch[x][0]=ch[x][1]=0; 40 return; 41 } 42 43 il int divide(RG int l,RG int r){ 44 if (l>r) return 0; RG int mid=(l+r)>>1; 45 ch[st[mid]][0]=divide(l,mid-1); 46 ch[st[mid]][1]=divide(mid+1,r); 47 pushup(st[mid]); return st[mid]; 48 } 49 50 il void rebuild(RG int &x){ top=0,dfs(x),x=divide(1,top); return; } 51 52 il int qrank(RG int x,RG int k){ 53 RG int res=1; 54 while (x){ 55 if (k<=val[x]) x=ch[x][0]; 56 else res+=sz[ch[x][0]]+(!del[x]),x=ch[x][1]; 57 } 58 return res; 59 } 60 61 il int find(RG int x,RG int k){ 62 while (x){ 63 if (!del[x] && k==sz[ch[x][0]]+1) return val[x]; 64 if (k<=sz[ch[x][0]]) x=ch[x][0]; 65 else k-=sz[ch[x][0]]+(!del[x]),x=ch[x][1]; 66 } 67 return val[x]; 68 } 69 70 il int* Insert(RG int &x,RG int k){ 71 if (!x){ val[x=++tot]=k,sz[x]=cover[x]=1; return NULL; } 72 sz[x]++,cover[x]++; int *p=Insert(ch[x][val[x]<=k],k); 73 if (max(cover[ch[x][0]],cover[ch[x][1]])>cover[x]*alpha) p=&x; 74 return p; 75 } 76 77 il void insert(RG int k){ int *x=Insert(rt,k); if (x) rebuild(*x); return; } 78 79 il void Erase(RG int x,RG int k){ 80 while (x){ 81 sz[x]--; if (!del[x] && k==sz[ch[x][0]]+1){ del[x]=1; return; } 82 if (k<=sz[ch[x][0]]) x=ch[x][0]; else k-=sz[ch[x][0]]+(!del[x]),x=ch[x][1]; 83 } 84 return; 85 } 86 87 il void erase(RG int k){ Erase(rt,qrank(rt,k)); if (sz[rt]<cover[rt]*alpha) rebuild(rt); return; } 88 89 il void work(){ 90 Q=gi(); RG int type,x; 91 while (Q--){ 92 type=gi(),x=gi(); 93 if (type==1) insert(x); 94 if (type==2) erase(x); 95 if (type==3) printf("%d\n",qrank(rt,x)); 96 if (type==4) printf("%d\n",find(rt,x)); 97 if (type==5) printf("%d\n",find(rt,qrank(rt,x)-1)); 98 if (type==6) printf("%d\n",find(rt,qrank(rt,x+1))); 99 } 100 return; 101 } 102 103 int main(){ 104 File("tree"); 105 work(); 106 return 0; 107 }
最近又学了一下非旋转$treap$:
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define PR pair<int,int> 6 #define inf (1<<30) 7 #define N (100010) 8 9 using namespace std; 10 11 int val[N],key[N],sz[N],ls[N],rs[N],rt,n,tot; 12 13 il int gi(){ 14 RG int x=0,q=1; RG char ch=getchar(); 15 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 16 if (ch=='-') q=-1,ch=getchar(); 17 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 18 return q*x; 19 } 20 21 il void pushup(RG int x){ 22 sz[x]=sz[ls[x]]+sz[rs[x]]+1; return; 23 } 24 25 il int merge(RG int x,RG int y){ 26 if (!x || !y) return x|y; 27 if (key[x]<key[y]){ 28 rs[x]=merge(rs[x],y),pushup(x); return x; 29 } else{ 30 ls[y]=merge(x,ls[y]),pushup(y); return y; 31 } 32 } 33 34 il PR split(RG int x,RG int k){ 35 if (!x) return make_pair(0,0); RG PR P; 36 if (k<=sz[ls[x]]) P=split(ls[x],k),ls[x]=P.second,P.second=x; 37 else P=split(rs[x],k-sz[ls[x]]-1),rs[x]=P.first,P.first=x; 38 pushup(x); return P; 39 } 40 41 il int rk(RG int x,RG int k){ 42 RG int res=0,tmp=inf; 43 while (x){ 44 if (k==val[x]) tmp=min(tmp,res+sz[ls[x]]+1); 45 k<=val[x]?x=ls[x]:(res+=sz[ls[x]]+1,x=rs[x]); 46 } 47 return tmp==inf ? res : tmp; 48 } 49 50 il int find(RG int x,RG int k){ 51 if (k==sz[ls[x]]+1) return val[x]; 52 if (k<=sz[ls[x]]) return find(ls[x],k); 53 return find(rs[x],k-sz[ls[x]]-1); 54 } 55 56 il int pre(RG int x,RG int k){ 57 if (!x) return -inf; 58 if (k>val[x]) return max(val[x],pre(rs[x],k)); 59 return pre(ls[x],k); 60 } 61 62 il int nxt(RG int x,RG int k){ 63 if (!x) return inf; 64 if (k<val[x]) return min(val[x],nxt(ls[x],k)); 65 return nxt(rs[x],k); 66 } 67 68 il void insert(RG int x){ 69 sz[++tot]=1,val[tot]=x,key[tot]=rand()<<15|rand(); 70 RG int k=rk(rt,x); 71 RG PR P=split(rt,k); 72 rt=merge(merge(P.first,tot),P.second); 73 } 74 75 il void del(RG int x){ 76 RG int k=rk(rt,x); 77 RG PR P1=split(rt,k); 78 RG PR P2=split(P1.first,k-1); 79 rt=merge(P2.first,P1.second); 80 } 81 82 int main(){ 83 #ifndef ONLINE_JUDGE 84 freopen("treap.in","r",stdin); 85 freopen("treap.out","w",stdout); 86 #endif 87 srand(19260817); n=gi(); 88 for (RG int i=1,op,x;i<=n;++i){ 89 op=gi(),x=gi(); 90 if (op==1) insert(x); if (op==2) del(x); 91 if (op==3) printf("%d\n",rk(rt,x)); 92 if (op==4) printf("%d\n",find(rt,x)); 93 if (op==5) printf("%d\n",pre(rt,x)); 94 if (op==6) printf("%d\n",nxt(rt,x)); 95 } 96 return 0; 97 }