BZOJ 3224 普通平衡树
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]
Source
平衡树裸题,splay大法好。
1 #include<queue> 2 #include<cstdio> 3 #include<cstdlib> 4 using namespace std; 5 6 #define maxn 100010 7 const int inf = 1 << 30; 8 queue <int> team; 9 struct TREE 10 { 11 int ch[maxn][2],fa[maxn],cnt,root; 12 int key[maxn],size[maxn],t[maxn]; 13 14 inline int newnode() 15 { 16 if (team.empty()) return ++cnt; 17 int ret = team.front(); team.pop(); 18 return ret; 19 } 20 21 inline TREE() 22 { 23 root = newnode(); 24 key[root] = -inf; ++t[root]; 25 updata(root); 26 add(inf); 27 } 28 29 inline int find(int rank,int have,int now) 30 { 31 if (have+size[ch[now][0]]<rank&&have+size[ch[now][0]]+t[now]>=rank) return now; 32 if (have+size[ch[now][0]]+t[now]<rank) return find(rank,have+size[ch[now][0]]+t[now],ch[now][1]); 33 else return find(rank,have,ch[now][0]); 34 } 35 36 inline void updata(int now) { size[now] = size[ch[now][0]] + size[ch[now][1]] + t[now]; } 37 38 inline void rotate(int x) 39 { 40 int y = fa[x],z = fa[y],l = ch[y][0] != x,r = l ^ 1; 41 if (z != 0) ch[z][ch[z][0] != y] = x; 42 fa[x] = z; fa[y] = x; fa[ch[x][r]] = y; 43 ch[y][l] = ch[x][r]; ch[x][r] = y; 44 updata(y); updata(x); 45 } 46 47 inline void splay(int x,int aim) 48 { 49 int p = fa[aim]; 50 while (fa[x] != p) 51 { 52 int y = fa[x],z = fa[y]; 53 if (z != p) 54 { 55 if ((ch[z][0] == y)^(ch[y][0] == x)) rotate(x); 56 else rotate(y); 57 } 58 rotate(x); 59 } 60 if (aim == root) root = x; 61 } 62 63 inline int search(int x) 64 { 65 int now = root; 66 while (now) 67 { 68 if (key[now] == x) break; 69 now = ch[now][x > key[now]]; 70 } 71 return now; 72 } 73 74 inline void add(int x) 75 { 76 int now = root,pre = 0; 77 while (now) 78 { 79 pre = now; 80 now = ch[now][x > key[now]]; 81 } 82 now = newnode(); 83 fa[now] = pre; ch[pre][x > key[pre]] = now; 84 key[now] = x; ++t[now]; 85 pre = now; 86 while (now) 87 { 88 updata(now); 89 now = fa[now]; 90 } 91 splay(pre,root); 92 } 93 94 inline int qrank(int x) 95 { 96 int now = root,ret = 0; 97 while (key[now] != x) 98 { 99 if (x < key[now]) now = ch[now][0]; 100 else ret += size[ch[now][0]] + t[now],now = ch[now][1]; 101 } 102 return ret + size[ch[now][0]] + 1; 103 } 104 105 inline void insert(int x) 106 { 107 int p = search(x); 108 if (p) 109 { 110 splay(p,root); 111 ++t[p]; 112 updata(p); 113 } 114 else add(x); 115 } 116 117 inline void del(int x) 118 { 119 int now = search(x),k = qrank(x); 120 int p = find(k-1,0,root),q = find(k + t[now],0,root); 121 splay(p,root); 122 splay(q,ch[p][1]); 123 if (--t[now]) 124 { 125 updata(now); 126 updata(q); 127 updata(p); 128 } 129 else 130 { 131 ch[q][0] = 0; fa[now] = 0; 132 updata(q); 133 updata(p); 134 team.push(now); 135 } 136 } 137 138 inline int ask(int x,int sign) 139 { 140 int now = root,ret; 141 while (now) 142 { 143 if (sign) 144 { 145 if (key[now] > x) 146 ret = now,now = ch[now][0]; 147 else now = ch[now][1]; 148 } 149 else 150 { 151 if (key[now] < x) 152 ret = now,now = ch[now][1]; 153 else now = ch[now][0]; 154 } 155 } 156 return key[ret]; 157 } 158 }tree; 159 160 inline int read() 161 { 162 int x=0,f=1;char ch=getchar(); 163 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 164 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 165 return x*f; 166 } 167 168 int main() 169 { 170 freopen("3224.in","r",stdin); 171 freopen("3224.out","w",stdout); 172 int T = read(); 173 while (T--) 174 { 175 int opt = read(); 176 if (opt == 1) tree.insert(read()); 177 else if (opt == 2) tree.del(read()); 178 else if (opt == 3) printf("%d\n",tree.qrank(read())-1); 179 else if (opt == 4) printf("%d\n",tree.key[tree.find(read()+1,0,tree.root)]); 180 else if (opt == 5) printf("%d\n",tree.ask(read(),0)); 181 else printf("%d\n",tree.ask(read(),1)); 182 } 183 fclose(stdin); fclose(stdout); 184 return 0; 185 }
高考结束,重新回归。