BZOJ3224 普通平衡树

来源:互联网 发布:淘宝直通车品牌资质 编辑:程序博客网 时间:2024/04/27 20:18
题目传送门

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每行输出一个数,表示对应答案
题解
这道题很明显要用二叉排序树来进行操作,其实是裸题。不过以前没打过splay,考试时教练让我们打splay。没打出来,调了一晚上也没调出来。wwwww。熬夜打了一个treap,还要上课啊。。。。。补觉了。
#include <cstdio>#include <iostream>#include <algorithm>#include <cstdlib>#include <ctime>using namespace std;const int Maxn = 101111;struct node {int s,v,r,cnt; int ch[2];}N[Maxn];int totN, root;const int INF = 1 << 30;void up(int u) {int ls = N[u].ch[0], rs = N[u].ch[1];N[u].s = N[u].cnt + N[ls].s + N[rs].s;}void Rot(int &u, int d) {int t = N[u].ch[d^1];  N[u].ch[d^1] = N[t].ch[d];N[t].ch[d] = u;up(u); up(t); u = t;}void Ins(int& u,int val) {if (!u) {u = ++totN; N[u].v = val; N[u].cnt = 1; N[u].s = 1; N[u].r = rand();} else {++N[u].s; int k = val < N[u].v ? 0 : 1;if (N[u].v == val) { ++N[u].cnt; return; }Ins(N[u].ch[k], val);if (N[N[u].ch[k]].r > N[u].r) Rot(u, k ^ 1);}}void Del(int& u,int val) {if (!u) return;if (N[u].v == val) {if (N[u].cnt > 1) { --N[u].cnt; --N[u].s; return; }if (!N[u].ch[0] || !N[u].ch[1]) u = N[u].ch[0] + N[u].ch[1];else {int k = N[N[u].ch[0]].r > N[N[u].ch[1]].r;Rot(u,k); Del(u, val); }} else --N[u].s, Del(N[u].ch[val < N[u].v ? 0 : 1],val);}int Rank(int u, int val) {if (!u) return 0;if (N[u].v == val) return N[N[u].ch[0]].s + 1;if (N[u].v < val) return N[N[u].ch[0]].s + N[u].cnt + Rank(N[u].ch[1],val);else return Rank(N[u].ch[0],val);}int Kth(int u,int k) {if (!u) return 0;if (k <= N[N[u].ch[0]].s) return Kth(N[u].ch[0],k);if (k > N[N[u].ch[0]].s + N[u].cnt) return Kth(N[u].ch[1],k - N[N[u].ch[0]].s - N[u].cnt);return N[u].v;}int pred(int u, int val) {if (!u) return INF;if (val <= N[u].v) return pred(N[u].ch[0],val);int ans = pred(N[u].ch[1],val);if (ans == INF) ans = N[u].v;return ans;}int succ(int u, int val) {if (!u) return INF;if (val >= N[u].v) return succ(N[u].ch[1],val);int ans = succ(N[u].ch[0],val);if (ans == INF) ans = N[u].v;return ans;}int main() {//freopen("A.in","r",stdin);//freopen("A.out","w",stdout);int n, op, x;scanf("%d", &n);srand(time(NULL));while (n--) {scanf("%d%d", &op, &x);if (op == 1) Ins(root,x);else if (op == 2) Del(root,x);else if (op == 3) printf("%d\n", Rank(root,x));else if (op == 4) printf("%d\n", Kth(root,x));else if (op == 5) printf("%d\n", pred(root,x));else printf("%d\n",succ(root,x));}return 0;}
附:在网上看见了一个模板,把splay,treap和SBT的做法打了出来。
传送门在这里

0 1