【模板】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
", rank(r, x));
        else if (opt == 4) printf("%d
", num(r, x));
        else if (opt == 5) {s1 = -INF; pre(r, x); printf("%d
", s1); }
        else {s2 = INF; suc(r, x); printf("%d
", s2); }
    }
}
原文地址:https://www.cnblogs.com/xuyixuan/p/9445100.html