【模板】Splay
题意简述
已知一个数列,你需要进行下面六种操作:
1.插入 x 数
2.删除 x 数(若有多个相同的数,因只删除一个)
3.查询 x 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
4.查询排名为 x 的数
5.求 x 的前驱(前驱定义为小于 x ,且最大的数)
6.求 x 的后继(后继定义为大于 x ,且最小的数)
代码
#include <cstdio>
#include <algorithm>
const int INF = 0x3f3f3f3f;
int n, opt, x, s1, s2;
struct Node
{
int v, s, n;
Node *c[2];
Node(int x = 0) {v = x; s = n = 1; c[0] = c[1] = 0; }
int get(const bool& b) {return c[b] ? c[b] -> s : 0; }
void update() {s = get(0) + get(1) + n; }
int cmp(const int& x, const bool& b)
{
if (!b) return x == v ? -1 : x > v;
if (get(0) + 1 <= x && x <= get(0) + n) return -1;
return x > get(0);
}
}*r;
inline void rotate(Node* &o, const bool& b)
{
Node *t = o -> c[!b];
o -> c[!b] = t -> c[b];
t -> c[b] = o;
o -> update(); t -> update();
o = t;
}
void splay(Node* &o, int x, const bool& b)
{
int d1 = o -> cmp(x, b);
if (d1 == -1) return;
Node* &t = o -> c[d1];
if (b && d1) x -= o -> get(0) + o -> n;
int d2 = t -> cmp(x, b);
if (d2 != -1)
{
if (b && d2) x -= t -> get(0) + t -> n;
splay(t -> c[d2], x, b);
if (d1 == d2) rotate(o, !d1);
else rotate(t, !d2);
}
rotate(o, !d1);
}
void ins(Node* &o, const int& x)
{
if (!o) {o = new Node(x); return; }
Node* t = o;
int d = t -> cmp(x, 0);
while (d != -1 && t -> c[d]) t = t -> c[d], d = t -> cmp(x, 0);
if (d == -1) {++t -> n; t -> update(); return; }
t -> c[d] = new Node(x);
}
inline void del(Node* &o, const int& x)
{
splay(o, x, 0);
if (o -> n > 1) {--o -> n; o -> update(); return; }
Node* t = o;
if (!o -> c[0]) {o = o -> c[1]; delete t; return; }
splay(o -> c[0], o -> get(0), 1);
o -> c[0] -> c[1] = o -> c[1];
o = o -> c[0]; o -> update();
delete t;
}
inline int rank(Node* &o, const int& x) {splay(o, x, 0); return o -> get(0) + 1; }
inline int num(Node* &o, const int& x) {splay(o, x, 1); return o -> v; }
void pre(Node* &o, const int& x)
{
if (!o) return;
int d = o -> cmp(x, 0);
if (d == 1) s1 = std::max(s1, o -> v);
pre(o -> c[d == -1 ? 0 : d], x);
}
void suc(Node* &o, const int& x)
{
if (!o) return;
int d = o -> cmp(x, 0);
if (d == 0) s2 = std::min(s2, o -> v);
suc(o -> c[d == -1 ? 1 : d], x);
}
int main()
{
scanf("%d", &n);
for (register int i = 1; i <= n; ++i)
{
scanf("%d%d", &opt, &x);
if (opt == 1) ins(r, x), splay(r, x, 0);
else if (opt == 2) del(r, x);
else if (opt == 3) printf("%d\n", rank(r, x));
else if (opt == 4) printf("%d\n", num(r, x));
else if (opt == 5) {s1 = -INF; pre(r, x); printf("%d\n", s1); }
else {s2 = INF; suc(r, x); printf("%d\n", s2); }
}
}