protagonist

普通平衡树

问题 g: 普通平衡树

时间限制: 1 Sec  内存限制: 128 MB
提交: 20  解决: 16
[提交] [状态] [命题人:admin]

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1.插入x数
2.删除x数(若有多个相同的数,因只删除一个)
3.查询x数的排名(若有多个相同的数,因输出最小的排名)
4.查询排名为x的数
5.求x的前驱(前驱定义为小于x,且最大的数)
6.求x的后继(后继定义为大于x,且最小的数)

 

输入

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

 

输出

对于操作3,4,5,6每行输出一个数,表示对应答案

 

样例输入

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

样例输出

106465
84185
492737

 

提示

1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;

int son[maxn][6], val[maxn], size[maxn], root, sz, fa[maxn];
int key[maxn];

inline void clear(int cur) {
    son[cur][0] = son[cur][1] = fa[cur] = val[cur] = key[cur] = size[cur] = 0;
}

inline void update(int cur) {
    if (cur) {
        size[cur] = val[cur];
        if (son[cur][0]) {
            size[cur] += size[son[cur][0]];
        }
        if (son[cur][1]) {
            size[cur] += size[son[cur][1]];
        }
    }
}

inline int get(int cur) {
    return son[fa[cur]][1] == cur;
}


inline void rotate(int cur) {
    int old = fa[cur], fold = fa[old], re = get(cur);
    son[old][re] = son[cur][re ^ 1];
    fa[son[old][re]] = old;
    son[cur][re ^ 1] = old;
    fa[cur] = fold;
    fa[old] = cur;
    if (fold) {
        son[fold][son[fold][1] == old] = cur;
    }
    update(old);
    update(cur);
}

inline void splay(int cur) {
    for (register int i; i = fa[cur]; rotate(cur)) {
        if (fa[i]) {
            rotate(get(cur) == get(i) ? i : cur);
        }
    }
    root = cur;
}

inline int before() {
    int pos = son[root][0];
    while (son[pos][1]) {
        pos = son[pos][1];
    }
    return pos;
}

inline int nx() {
    int pos = son[root][1];
    while (son[pos][0]) {
        pos = son[pos][0];
    }
    return pos;
}

inline void add(int cur) {
    if (!root) {
        ++sz;
        son[sz][0] = son[sz][1] = fa[sz] = 0;
        root = sz;
        size[sz] = val[sz] = 1;
        key[sz] = cur;
        return;
    }
    int id = root, f = 0;
    while (true) {
        if (cur == key[id]) {
            val[id]++;
            update(id);
            update(f);
            splay(id);
            break;
        }
        f = id;
        id = son[id][key[id] < cur];
        if (!id) {
            sz++;
            son[sz][0] = son[sz][1] = 0;
            fa[sz] = f;
            size[sz] = val[sz] = 1;
            son[f][key[f] < cur] = sz;
            key[sz] = cur;
            update(f);
            splay(sz);
            break;
        }
    }
}


inline int find_rk(int cur) {
    int id = root, res = 0;
    while (true) {
        if (cur < key[id]) {
            id = son[id][0];
        } else {
            if (son[id][0]) {
                res += size[son[id][0]];
            }
            if (cur == key[id]) {
                splay(id);
                return res + 1;
            }
            res += val[id];
            id = son[id][1];
        }
    }
}

inline int find_sa(int cur) {
    int pre = root;
    while (true) {
        if (son[pre][0] && cur <= size[son[pre][0]]) {
            pre = son[pre][0];
        } else {
            int tot = (son[pre][0] ? size[son[pre][0]] : 0) + val[pre];
            if (cur <= tot) {
                return key[pre];
            }
            cur -= tot;
            pre = son[pre][1];
        }
    }
}

inline void del(int cur) {
    int pre = find_rk(cur);
    if (val[root] > 1) {
        val[root]--;
        update(root);
        return;
    }
    if (!son[root][0] && !son[root][1]) {
        clear(root);
        root = 0;
        return;
    }
    if (!son[root][0]) {
        int e = root;
        root = son[root][1];
        fa[root] = 0;
        clear(e);
        return;
    } else if (!son[root][1]) {
        int e = root;
        root = son[root][0];
        fa[root] = 0;
        clear(e);
        return;
    }
    int pf = before(), re = root;
    splay(pf);
    son[root][1] = son[re][1];
    fa[son[root][1]] = root;
    clear(re);
    update(root);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("splay.txt", "r", stdin);
#endif
    int n, opt, x;
    scanf("%d", &n);
    while (n--) {
        scanf("%d%d", &opt, &x);
        switch (opt) {
            case 1:
                add(x);
                break;
            case 2:
                del(x);
                break;
            case 3:
                printf("%d\n", find_rk(x));
                break;
            case 4:
                printf("%d\n", find_sa(x));
                break;
            case 5:
                add(x);
                printf("%d\n", key[before()]);
                del(x);
                break;
            case 6:
                add(x);
                printf("%d\n", key[nx()]);
                del(x);
                break;
        }
    }
    return 0;
}

 

 

posted @ 2019-09-10 13:25  czy-power  阅读(340)  评论(0编辑  收藏  举报