[BZOJ 3224]Tyvj 1728 普通平衡树
2017-12-16 14:01
495 查看
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
101 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
10646584185
492737
HINT
1.n的数据范围:n<=1000002.每个数的数据范围:[-2e9,2e9]
题解
作为一个模板题放在这里,准备写4个常用的平衡树。算是个坑...1 Splay
1.1 插入操作
一般平衡树的操作,不多赘述。1.2 删除操作
我们考虑删除数$x$:我们将$x$的前驱和后继找到。两个找到之后再将前驱通过$splay$操作旋到根,再将后继旋成前驱的儿子,删除后继的左儿子即可。显然能够保证后继的左儿子只有一个。
至于为什么要前驱和后继都找到之后再旋转,是因为查找的时候会将其他的节点旋转到根。
1.3 查询名次
我们通过维护子树大小来实现这一功能。某个数的名次其实就是当它旋转到根的时候左子树的大小+1。
我们对于每次插入操作,删除操作,$rotate$操作都要更新名次。
1.4 查询Kth数
递归实现。若左子树大小+1 <= 查询名次 <= 左子树大小+根节点数个数,结果就是当前数;
若查询名次 <= 左子树大小+1,递归查询左子树;
若查询名次 >= 左子树大小+根节点数个数,将查询名次-=左子树大小+根节点数个数,递归查询右子树。
1.5 查找前驱
通过$find$操作,找到“接近”这个数的数的位置。为什么是“接近”,是因为可能$splay$中可能不存在这个数,不存在的话我们就假想最后停在的节点就是这个数。
将其旋到根。判断这个数与根节点的数的关系,若小于(即不存在查询的数)显然这个数就是前驱。
若非,就查询其左子树“最靠右的那个数”。
1.6 查找后继
和查找前驱类似。//It is made by Awson on 2017.12.15 #include <map> #include <set> #include <cmath> #include <ctime> #include <queue> #include <stack> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) using namespace std; const int N = 100000; const int INF = ~0u>>1; struct fhq_Treap { int ch[N+5][2], lev[N+5], size[N+5], key[N+5], tot, root; queue<int>mem; int newnode(int keyy) { int o; if (!mem.empty()) o = mem.front(), mem.pop(); else o = ++tot; ch[o][0] = ch[o][1] = 0; size[o] = 1; key[o] = keyy, lev[o] = rand(); return o; } void pushup(int o) { size[o] = size[ch[o][0]]+size[ch[o][1]]+1; } void split(int o, int keyy, int &x, int &y) { if (!o) x = y = 0; else { if (key[o] <= keyy) x = o, split(ch[o][1], keyy, ch[o][1], y); else y = o, split(ch[o][0], keyy, x, ch[o][0]); pushup(o); } } int merge(int x, int y) { if (!x || !y) return x+y; if (lev[x] < lev[y]) { ch[x][1] = merge(ch[x][1], y); pushup(x); return x; }else { ch[y][0] = merge(x, ch[y][0]); pushup(y); return y; } } void insert(int keyy) { int r1, r2; split(root, keyy, r1, r2); root = merge(merge(r1, newnode(keyy)), r2); } void delet(int keyy) { int r1, r2, r3; split(root, keyy-1, r1, r2); split(r2, keyy, r2, r3); mem.push(r2); r2 = merge(ch[r2][0], ch[r2][1]); root = merge(merge(r1, r2), r3); } int rank(int keyy) { int r1, r2; split(root, keyy-1, r1, r2); int ans = size[r1]+1; root = merge(r1, r2); return ans; } int get_num(int o, int rk) { if (size[ch[o][0]]+1 == rk) return key[o]; if (size[ch[o][0]] >= rk) return get_num(ch[o][0], rk); return get_num(ch[o][1], rk-1-size[ch[o][0]]); } int get_pre(int keyy) { int r1, r2; split(root, keyy-1, r1, r2); int o = r1; while (ch[o][1]) o = ch[o][1]; int ans = key[o]; root = merge(r1, r2); return ans; } int get_nex(int keyy) { int r1, r2; split(root, keyy, r1, r2); int o = r2; while (ch[o][0]) o = ch[o][0]; int ans = key[o]; root = merge(r1, r2); return ans; } }T; int n, opt, x; void work() { srand(time(0)); scanf("%d", &n); while (n--) { scanf("%d%d", &opt, &x); if (opt == 1) T.insert(x); else if (opt == 2) T.delet(x); else if (opt == 3) printf("%d\n", T.rank(x)); else if (opt == 4) printf("%d\n", T.get_num(T.root, x)); else if (opt == 5) printf("%d\n", T.get_pre(x)); else printf("%d\n", T.get_nex(x)); } } int main() { work(); return 0; }
fhq_Treap
相关文章推荐
- bzoj 3224 Tyvj 1728 普通平衡树
- bzoj3224: Tyvj 1728 普通平衡树(平衡树)
- bzoj3224 Tyvj 1728 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树
- bzoj 3224 Tyvj 1728 普通平衡树 [Splay]
- BZOJ 3224 Tyvj 1728 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树 pb_ds
- BZOJ 3224: Tyvj 1728 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树 treap
- 【BZOJ】3224 Tyvj 1728 普通平衡树 平衡树模板
- BZOJ 3224: Tyvj 1728 普通平衡树(BST)
- bzoj 3224==tyvj 1728普通平衡树 splay
- 【BZOJ3224】Tyvj1728普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树 替罪羊树
- bzoj 3224,tyvj 1728普通平衡树
- 【权值分块】bzoj3224 Tyvj 1728 普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- 【Treap】[BZOJ 3224]Tyvj 1728 普通平衡树 & 非旋转实现
- 【bzoj】3224: Tyvj 1728 普通平衡树