[平衡树模板]Treap

来源:互联网 发布:老七的淘宝店 编辑:程序博客网 时间:2024/05/29 03:18
算法标签 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;}