HYSBZ - 3224 Tyvj 1728 普通平衡树——splay

模板题,不过看了leaderboard后发现了更好的递归式splay,等下学一下

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
struct Splay_tree {
    int f[maxn], ch[maxn][2], key[maxn], cnt[maxn], size[maxn], sz, root;
    void clear() { sz = root = 0; }
    void init0(int x) {
        f[x] = ch[x][0] = ch[x][1] = key[x] = cnt[x] = size[x] = 0;
    }
    void init(int x, int fa, int v) {
        f[x] = fa; ch[x][0] = ch[x][1] = 0; key[x] = v; cnt[x] = size[x] = 1;
    }
    int witch(int x) { return ch[f[x]][1]==x; }
    void update(int x) {
        if (!x) return;
        size[x] = cnt[x];
        if (ch[x][0]) size[x] += size[ch[x][0]];
        if (ch[x][1]) size[x] += size[ch[x][1]];
    }
    void rotate(int x) {
        int y = f[x], z = f[y], px = witch(x), py = witch(y);
        ch[y][px]=ch[x][px^1]; f[ch[y][px]] = y;
        ch[x][px^1]=y; f[y] = x;
        f[x]=z; if (z) ch[z][py]=x;
        update(y); update(x);
    }
    void splay(int x) {
        for (int fa; (fa = f[x]); rotate(x)) if (f[fa]) rotate(witch(x)==witch(fa)?fa:x);
        root = x;
    }
    void insert(int v) {
        if (!root) { init(++sz, 0, v); root = sz; return; }
        int fa = 0, now = root;
        while (true) {
            if (now == 0) {
                init(++sz, fa, v);
                ch[fa][key[fa]<v]=sz;
                update(fa); splay(sz); break;
            }
            if (key[now]==v) {
                cnt[now]++;
                update(now); update(fa); splay(now); break;
            }
            fa = now;
            now = ch[now][key[now]<v];
        }
    }
    int find(int v) {
        int ans = 0, now = root;
        while (true) {
            if (!now) return -1;
            if (v < key[now]) now = ch[now][0];
            else {
                ans += (ch[now][0]?size[ch[now][0]]:0);
                if (v == key[now]) { splay(now); return ans+1; }
                ans += cnt[now];
                now = ch[now][1];
            }
        }
    }
    int findx(int x) {
        int now = root;
        while (true) {
            if (!now) return -1;
            if (ch[now][0] && x <= size[ch[now][0]]) now = ch[now][0];
            else {
                int t = (ch[now][0]?size[ch[now][0]]:0)+cnt[now];
                if (x <= t) return key[now];
                x -= t; now = ch[now][1];
            }
        }
    }
    int pre(){
        int now=ch[root][0];
        while (ch[now][1]) now=ch[now][1];
        return now;
    }
    int next(){
        int now=ch[root][1];
        while (ch[now][0]) now=ch[now][0];
        return now;
    }
    void del(int x) {
        int t = find(x);
        if (cnt[root] > 1) { cnt[root]--; update(root); return; }
        if (!ch[root][0]&&!ch[root][1]) { init0(root); root = 0; return; }
        if (!ch[root][0]) {
            t = root; root = ch[root][1]; f[root] = 0; init0(t); return;
        }
        if (!ch[root][1]) {
            t = root; root = ch[root][0]; f[root] = 0; init0(t); return;
        }
        int p = pre(); t = root;
        splay(p); f[ch[t][1]] = root; ch[root][1] = ch[t][1]; init0(t);
        update(root);
    }
}splay_tree;

int main() {
    splay_tree.sz = 0, splay_tree.root = 0;
    int T;
    scanf("%d", &T);
    while (T--) {
        int opt, x;
        scanf("%d%d", &opt, &x);
        if (opt == 1) splay_tree.insert(x);
        else if (opt == 2) splay_tree.del(x);
        else if (opt == 3) printf("%d\n", splay_tree.find(x));
        else if (opt == 4) printf("%d\n", splay_tree.findx(x));
        else if (opt == 5) {
            splay_tree.insert(x);
            printf("%d\n", splay_tree.key[splay_tree.pre()]);
            splay_tree.del(x);
        }
        else {
            splay_tree.insert(x);
            printf("%d\n", splay_tree.key[splay_tree.next()]);
            splay_tree.del(x);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/80072976
今日推荐