3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 23161 Solved: 10527
[Submit][Status][Discuss]
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]
Source
题解:板题Orz,直接模板即可
1 /************************************************************** 2 Problem: 3224 3 User: SongHL 4 Language: C++ 5 Result: Accepted 6 Time:664 ms 7 Memory:3648 kb 8 ****************************************************************/ 9 10 /********************************** 11 Scapegoat Tree(Sag)普通平衡树 12 ***********************************/ 13 //1. 插入x数 14 //2. 删除x数(若有多个相同的数,因只删除一个) 15 //3. 查询x数的排名(若有多个相同的数,因输出最小的排名) 16 //4. 查询排名为x的数 17 //5. 求x的前驱(前驱定义为小于x,且最大的数) 18 //6. 求x的后继(后继定义为大于x,且最小的数) 19 #include<bits/stdc++.h> 20 using namespace std; 21 const int MAXN=1e5+5; 22 int F[MAXN],lch[MAXN],rch[MAXN],key[MAXN],size[MAXN],num[MAXN]; 23 int sz=0,root=0; 24 25 inline void Pushup(int x) 26 { 27 size[x]=num[x]; 28 if(lch[x]) size[x]+=size[lch[x]]; 29 if(rch[x]) size[x]+=size[rch[x]]; 30 } 31 //x==lch[f] 右旋 32 inline void zig(int x) 33 { 34 int f=F[x],gf=F[f]; 35 F[f]=x;F[x]=gf; 36 if(gf) 37 { 38 if(lch[gf]==f) lch[gf]=x; 39 else if(rch[gf]==f) rch[gf]=x; 40 } 41 lch[f]=rch[x]; 42 F[rch[x]]=f; 43 rch[x]=f; 44 Pushup(f);Pushup(x); 45 } 46 //x==rch[f] 左旋 47 inline void zag(int x) 48 { 49 int f=F[x],gf=F[f]; 50 F[f]=x;F[x]=gf; 51 if(gf) 52 { 53 if(lch[gf]==f) lch[gf]=x; 54 else if(rch[gf]==f) rch[gf]=x; 55 } 56 rch[f]=lch[x]; 57 F[lch[x]]=f; 58 lch[x]=f; 59 Pushup(f);Pushup(x); 60 } 61 62 inline void Splay(int x) 63 { 64 int f,gf; 65 while(F[x]!=0) 66 { 67 f=F[x];gf=F[f]; 68 if(gf==0) 69 { 70 if(x==lch[f]) zig(x); 71 else zag(x); 72 break; 73 } 74 if(f==lch[gf]&&x==lch[f]){zig(f);zig(x);} 75 else if(f==rch[gf]&&x==rch[f]){zag(f);zag(x);} 76 else if(f==rch[gf]&&x==lch[f]){zig(x);zag(x);} 77 else{zag(x);zig(x);} 78 } 79 root=x; 80 } 81 82 inline int Find(int x)//x的编号 83 { 84 int p=root; 85 while(x!=key[p]) 86 { 87 if(x<key[p]) 88 { 89 if(lch[p]==0) break; 90 else p=lch[p]; 91 } 92 else 93 { 94 if(rch[p]==0) break; 95 else p=rch[p]; 96 } 97 } 98 return p; 99 } 100 101 inline void Insert(int x) 102 { 103 if(sz==0) 104 { 105 key[++sz]=x;size[1]=1; 106 num[1]=1;root=1; 107 F[sz]=0; 108 return; 109 } 110 int p=Find(x); 111 if(key[p]!=x) 112 { 113 key[++sz]=x; 114 num[sz]=0; 115 F[sz]=p; 116 if(x<key[p]) lch[p]=sz; 117 else rch[p]=sz; 118 lch[sz]=rch[sz]=0; 119 p=sz; 120 } 121 num[p]++; 122 Pushup(p); 123 Pushup(F[p]); 124 Splay(p); 125 } 126 127 inline int FindMax(int p) 128 { 129 while(rch[p]!=0) p=rch[p]; 130 return p; 131 } 132 133 inline int FindMin(int p) 134 { 135 while(lch[p]!=0) p=lch[p]; 136 return p; 137 } 138 //删除x 139 inline void Delete(int x) 140 { 141 int p=Find(x); 142 Splay(p); num[p]--; 143 if(num[p]==0) 144 { 145 if(lch[p]==0) {root=rch[p];F[rch[p]]=0;} 146 else if(rch[p]==0) { root=lch[p];F[lch[p]]=0;} 147 else 148 { 149 int l=FindMax(lch[p]),r=rch[p]; 150 F[lch[p]]=0; 151 Splay(l); 152 rch[l]=r; 153 F[r]=l; 154 Pushup(l); 155 } 156 } 157 } 158 //排名为k 159 inline int FindKth(int k,int p) 160 { 161 if(size[lch[p]]<k&&k<=size[lch[p]]+num[p]) return p; 162 else if(k<=size[lch[p]]) return FindKth(k,lch[p]); 163 else if(rch[p]) return FindKth(k-size[lch[p]]-num[p],rch[p]); 164 } 165 166 int main() 167 { 168 int op,n,x; 169 scanf("%d",&n); 170 for(int i=1;i<=n;i++) 171 { 172 scanf("%d%d",&op,&x); 173 switch(op) 174 { 175 case 1: Insert(x);break; 176 case 2: Delete(x);break; 177 case 3: Splay(Find(x));printf("%d ",size[lch[root]]+1);break; 178 case 4: printf("%d ",key[FindKth(x,root)]);break; 179 case 5: Insert(x);printf("%d ",key[FindMax(lch[root])]);Delete(x);break; 180 case 6: Insert(x);printf("%d ",key[FindMin(rch[root])]);Delete(x);break; 181 } 182 } 183 return 0; 184 }