您的位置:首页 > 其它

[平衡树模板]Treap

2017-07-25 00:27 141 查看
算法标签 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: