问题 g: 普通平衡树
时间限制: 1 Sec 内存限制: 128 MB提交: 20 解决: 16
[提交] [状态] [命题人:admin]
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1.插入x数
2.删除x数(若有多个相同的数,因只删除一个)
3.查询x数的排名(若有多个相同的数,因输出最小的排名)
4.查询排名为x的数
5.求x的前驱(前驱定义为小于x,且最大的数)
6.求x的后继(后继定义为大于x,且最小的数)
1.插入x数
2.删除x数(若有多个相同的数,因只删除一个)
3.查询x数的排名(若有多个相同的数,因输出最小的排名)
4.查询排名为x的数
5.求x的前驱(前驱定义为小于x,且最大的数)
6.求x的后继(后继定义为大于x,且最小的数)
输入
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(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的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 10; int son[maxn][6], val[maxn], size[maxn], root, sz, fa[maxn]; int key[maxn]; inline void clear(int cur) { son[cur][0] = son[cur][1] = fa[cur] = val[cur] = key[cur] = size[cur] = 0; } inline void update(int cur) { if (cur) { size[cur] = val[cur]; if (son[cur][0]) { size[cur] += size[son[cur][0]]; } if (son[cur][1]) { size[cur] += size[son[cur][1]]; } } } inline int get(int cur) { return son[fa[cur]][1] == cur; } inline void rotate(int cur) { int old = fa[cur], fold = fa[old], re = get(cur); son[old][re] = son[cur][re ^ 1]; fa[son[old][re]] = old; son[cur][re ^ 1] = old; fa[cur] = fold; fa[old] = cur; if (fold) { son[fold][son[fold][1] == old] = cur; } update(old); update(cur); } inline void splay(int cur) { for (register int i; i = fa[cur]; rotate(cur)) { if (fa[i]) { rotate(get(cur) == get(i) ? i : cur); } } root = cur; } inline int before() { int pos = son[root][0]; while (son[pos][1]) { pos = son[pos][1]; } return pos; } inline int nx() { int pos = son[root][1]; while (son[pos][0]) { pos = son[pos][0]; } return pos; } inline void add(int cur) { if (!root) { ++sz; son[sz][0] = son[sz][1] = fa[sz] = 0; root = sz; size[sz] = val[sz] = 1; key[sz] = cur; return; } int id = root, f = 0; while (true) { if (cur == key[id]) { val[id]++; update(id); update(f); splay(id); break; } f = id; id = son[id][key[id] < cur]; if (!id) { sz++; son[sz][0] = son[sz][1] = 0; fa[sz] = f; size[sz] = val[sz] = 1; son[f][key[f] < cur] = sz; key[sz] = cur; update(f); splay(sz); break; } } } inline int find_rk(int cur) { int id = root, res = 0; while (true) { if (cur < key[id]) { id = son[id][0]; } else { if (son[id][0]) { res += size[son[id][0]]; } if (cur == key[id]) { splay(id); return res + 1; } res += val[id]; id = son[id][1]; } } } inline int find_sa(int cur) { int pre = root; while (true) { if (son[pre][0] && cur <= size[son[pre][0]]) { pre = son[pre][0]; } else { int tot = (son[pre][0] ? size[son[pre][0]] : 0) + val[pre]; if (cur <= tot) { return key[pre]; } cur -= tot; pre = son[pre][1]; } } } inline void del(int cur) { int pre = find_rk(cur); if (val[root] > 1) { val[root]--; update(root); return; } if (!son[root][0] && !son[root][1]) { clear(root); root = 0; return; } if (!son[root][0]) { int e = root; root = son[root][1]; fa[root] = 0; clear(e); return; } else if (!son[root][1]) { int e = root; root = son[root][0]; fa[root] = 0; clear(e); return; } int pf = before(), re = root; splay(pf); son[root][1] = son[re][1]; fa[son[root][1]] = root; clear(re); update(root); } int main() { #ifndef ONLINE_JUDGE freopen("splay.txt", "r", stdin); #endif int n, opt, x; scanf("%d", &n); while (n--) { scanf("%d%d", &opt, &x); switch (opt) { case 1: add(x); break; case 2: del(x); break; case 3: printf("%d ", find_rk(x)); break; case 4: printf("%d ", find_sa(x)); break; case 5: add(x); printf("%d ", key[before()]); del(x); break; case 6: add(x); printf("%d ", key[nx()]); del(x); break; } } return 0; }