[平衡树模板]Treap
2017-07-25 00:27
141 查看
算法标签 Treap
种下第一棵平衡树…
如果觉得这个题水的可以做一下4544压行,是千古神犇花爸爸出的神犇题。
您需要写一种数据结构(可参考题目标题,但是这句话其实并没有什么用233),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
注意:这道题重复数据可以加入Treap
种下第一棵平衡树…
题目描述 Description
这是一道模板题。如果觉得这个题水的可以做一下4544压行,是千古神犇花爸爸出的神犇题。
您需要写一种数据结构(可参考题目标题,但是这句话其实并没有什么用233),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
输入描述 Input Description
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)输出描述 Output Description
对于操作3,4,5,6每行输出一个数,表示对应答案注意:这道题重复数据可以加入Treap
#include <cstdio> #include <cstdlib> #include <algorithm> #include <ctime> using namespace std; const int maxn = 100005; struct node { node *ch[2]; int r, v, s; //v-键值 r-优先级 s - 子树结点个数 inline int cmp(int x) const { return x < v ? 0 : 1; } inline void maintain() { //计算子结点个数 s = 1; if(ch[0] != NULL) s += ch[0] -> s; if(ch[1] != NULL) s += ch[1] -> s; } }; void retate(node* &x, int d) //旋转, d = 0 左旋 d = 1 右旋 { node *k = x -> ch[d ^ 1]; x->ch[d ^ 1] = k -> ch[d]; k->ch[d] = x; x->maintain(); k->maintain(); //重新计算子结点个数 x = k; } void insert(node* &x, int k) //在以x为根的子树中插入键值k,修改x { if(x == NULL) {x = new node(); x -> ch[0] = x -> ch[1] = NULL; x -> v = k; x -> r = rand(); x -> s = 1; }//x为空 else { int d = x -> cmp(k); insert(x -> ch[d], k); if(x -> ch[d] -> r > x -> r) retate(x, d ^ 1); } x -> maintain(); } void remove(node* &x, int k) //在以x为根的子树中删除键值k,修改x { if(x -> v == k) { //k = x.v if(x -> ch[0] == NULL) x = x -> ch[1]; //左子树为空 else if(x -> ch[1] == NULL) x = x -> ch[0]; //右子树为空 else { int d = (x -> ch[0] -> r > x -> ch[1] -> r ? 1 : 0); retate(x, d); remove(x -> ch[d], k); //递归删除 } }else remove(x -> ch[x -> cmp(k)], k); if(x != NULL) x -> maintain(); } int Rank(node *x, int k) //查找k的排名 { if(x == NULL) return 1; if(k <= x -> v) return Rank(x ->ch[0], k); else return Rank(x -> ch[1], k) + (x -> ch[0] != NULL ? x -> ch[0] -> s : 0) + 1; } int kth(node *x, int k) //查找第k小元素 { if(x == NULL || k <= 0 || k > x -> s) return 0; int s = (x -> ch[0] == NULL ? 0 : x -> ch[0] -> s); if(s + 1 == k) return x -> v; else if(k <= s) return kth(x -> ch[0], k); else return kth(x -> ch[1], k - s - 1); } int last(node *x, int k) //求k的前驱 { if(x == NULL) return -(1 << 30); if(x -> v < k) return max(x -> v, last(x -> ch[1], k)); else return last(x -> ch[0], k); } int next(node *x, int k) //求k的后继 { if(x == NULL) return (1 << 30); if(x -> v > k) return min(x -> v, next(x -> ch[0], k)); else return next(x -> ch[1], k); } int main() { freopen("phs.in", "r", stdin); freopen("phs.out", "w", stdout); int cnt = 0, n; scanf("%d", &n); node *root = NULL; for(int x, opt, i = 1; i <= n; ++i) { scanf("%d%d", &opt, &x); if(opt == 1) insert(root, x); else if(opt == 2) remove(root, x); else if(opt == 3) printf("%d\n", Rank(root, x)); else if(opt == 4) printf("%d\n", kth(root, x)); else if(opt == 5) printf("%d\n", last(root, x)); else if(opt == 6) printf("%d\n", next(root, x)); } return 0; }
相关文章推荐
- 【模板】普通平衡树(Treap/SBT) 洛谷 3369 splay
- P3369 【模板】普通平衡树(Treap/SBT)
- [模板] fhqTreap (非旋Treap)+ 可持久化平衡树
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
- BZOJ 3224 普通平衡树 裸treap模板题
- 平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】
- P3369 【模板】普通平衡树(Treap/SBT)
- BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
- BZOJ 3224 洛谷 3369 【模板】普通平衡树(Treap/SBT)
- 平衡树——Treap (含完整模板)
- [模板]平衡树treap
- POJ 1442 平衡树Treap模板
- BZOJ3224:普通平衡树(含SBT、Treap、Splay模板)
- P3369 【模板】普通平衡树(Treap/SBT)(pb_ds版)
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
- 算法模板——平衡树Treap
- 【Treap模板详细注释】BZOJ3224-普通平衡树
- BZOJ3224:普通平衡树(含SBT、Treap、Splay模板)
- [BZOJ 3224]普通平衡树(忽然想要存个模板 Treap/Splay)