zoukankan      html  css  js  c++  java
  • 普通平衡树

    问题 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
    ", find_rk(x));
                    break;
                case 4:
                    printf("%d
    ", find_sa(x));
                    break;
                case 5:
                    add(x);
                    printf("%d
    ", key[before()]);
                    del(x);
                    break;
                case 6:
                    add(x);
                    printf("%d
    ", key[nx()]);
                    del(x);
                    break;
            }
        }
        return 0;
    }
  • 相关阅读:
    「codeforces
    「sdoi2019
    「ABC 218」解集
    「hdu
    「atcoder
    「tricks」平凡二分幻术
    并查集
    Bellman-Ford算法 & SPFA & SPFA_DFS
    最近公共祖先(LCA)
    题解 P5751 【[NOI1999]01串】
  • 原文地址:https://www.cnblogs.com/czy-power/p/11496981.html
Copyright © 2011-2022 走看看