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的做法打了出来。