#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1e5+2;
struct Splay {
struct node {
node *ch[2], *fa; int val, size;
node (node *fa = NULL, int val = 0) : fa(fa), val(val) {ch[0] = ch[1] = NULL; size = 1;}
inline bool isr () { return fa -> ch[1] == this;}
inline bool up () { size = (ch[0] ? ch[0] -> size : 0) + (ch[1] ? ch[1] -> size : 0) + 1;}
inline int rnk () { return (ch[0] ? ch[0] -> size : 0) + 1;}
}*root, pool[N], *tail, *st[N];
int top;
Splay () { tail = pool; root = NULL; top = 0;}
inline void rot (node *x) {
int k = x -> isr();
node *y = x -> fa, *z = y -> fa, *w = x -> ch[!k];
if (y == root) root = x; else z -> ch[y->isr()] = x;
x -> fa = z, y -> fa = x;
x -> ch[!k] = y, y -> ch[k] = w;
if (w) w -> fa = y;
y -> up(); x -> up();
}
inline void splay (node *x) {
while (x != root) {
if (x -> fa != root) rot (x -> isr() ^ x -> fa -> isr() ? x : x -> fa);
rot (x);
}
}
inline void Insert (int val) {
if (!root) return (void) (root = new (tail ++) node (NULL, val));
node *x = root, *fa = NULL;
while (x) {
fa = x;
x = x -> ch[val > x -> val];
}
x = new (tail ++) node (fa, val);
fa -> ch[val > fa -> val] = x; splay (x);
}
node *merge (node *x, node *y, node *fa) {
if (x) x -> fa = fa;
if (y) y -> fa = fa;
if (!x || !y) return x ? x : y;
return x -> ch[1] = merge (x -> ch[1], y, x), x -> up(), x;
}
inline void del (int val) {
node *x = root;
while (x && x -> val != val) x = x -> ch[val > x -> val];
if (x == NULL) return;
splay(x);
root = merge (x -> ch[0], x -> ch[1], NULL);
st[++top] = x, x = NULL;
}
inline int rnk (int val) {
node *x = root, *last = NULL; int res = 0;
while (x) {
last = x;
if (val <= x -> val) x = x -> ch[0];
else res += x -> rnk(), x = x -> ch[1];
}
return splay(last), res + 1;
}
inline int kth (int k) {
node *x = root;
while (x && x -> rnk() != k) {
if (x -> rnk() > k) x = x -> ch[0];
else k -= x -> rnk(), x = x -> ch[1];
}
return splay (x), x -> val;
}
inline int pre (int x) {return kth(rnk(x)-1);}
inline int nxt (int x) {return kth(rnk(x+1));}
inline void Action () {
int t;
scanf ("%d", &t);
while (t --> 0) {
int opt, x;
scanf ("%d%d", &opt, &x);
if (opt == 1) Insert (x);
if (opt == 2) del (x);
if (opt == 3) printf ("%d
", rnk(x));
if (opt == 4) printf ("%d
", kth(x));
if (opt == 5) printf ("%d
", pre(x));
if (opt == 6) printf ("%d
", nxt(x));
}
}
}yhm;
int main () { return yhm.Action(), 0;}
关于Splay的一些操作
1.$rot $
(k = x -> isr())
以及后文一些关于(ch[k])或者(ch[!k])的操作非常巧妙
回复数据的时候先(y -> up()) 然后再(x -> up())
因为x是y的爸爸
2.(splay)
有双链和单练之分 (防止退化成链)
ta与ta爹如果在同一个儿子的方向 就转一下ta爹
如果不在一个方向就转一下ta
3.关于(del) (rnk) (kth)
这几个函数写完之后需要记得splay一下
4.关于(isr) (rnk) (up)几个函数
inline bool isr () { return fa -> ch[1] == this;}
inline int up () { return siz = (ch[0] ? ch[0] -> siz : 0) + (ch[1] ? ch[1] -> siz : 0) + 1;}
inline int rnk () { return (ch[0] ? ch[0] -> siz : 0) + 1;}