zoukankan      html  css  js  c++  java
  • 「Splay」普通平衡树模板

    口诀:

    $rotate$:先上再下,最后自己

    $splay$:祖父未到旋两次,三点一线旋父亲,三点折线旋自己。

    $delete$:没有儿子就删光。单个儿子删自己。两个儿子找前驱。

    易错点:

    $rotate$:祖父不在自己做根

    $delete$:自己做根父亲为0

    $kth$:先减排名后转移

    /*By DennyQi 2018*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 100010;
    const int INF = 0x3f3f3f3f;
    inline int Max(const int a, const int b){ return (a > b) ? a : b; }
    inline int Min(const int a, const int b){ return (a < b) ? a : b; }
    inline int read(){
        int x = 0; int w = 1; register char c = getchar();
        for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
    }
    int n,opt,x,num_node;
    int ch[MAXN][2],fa[MAXN],val[MAXN],size[MAXN],cnt[MAXN],root;
    struct Splay{
        inline bool rson(int f, int x){
            return ch[f][1] == x;
        }
        inline void update(int x){
            size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x];
        }
        inline void clear(int x){
            val[x]=cnt[x]=size[x]=fa[x]=ch[x][0]=ch[x][1]=0;
        }
        inline void rotate(int x){
            int f = fa[x], gf = fa[f];
            bool p = rson(f, x), q = !p;
            if(gf) ch[gf][rson(gf,f)] = x; else root = x; fa[x] = gf;
            ch[f][p] = ch[x][q], fa[ch[x][q]] = f;
            ch[x][q] = f, fa[f] = x;
            update(f), update(x);
        }
        inline void splay(int x, int target){
            while(fa[x] != target){
                int f = fa[x], gf = fa[f];
                if(gf == target){ rotate(x); break;}
                if(rson(gf,f) == rson(f,x)) rotate(f); else rotate(x);
                rotate(x);
            }
        }
        inline void Insert(int v){
            int o = root;
            if(root == 0){
                root = ++num_node;
                cnt[root] = size[root] = 1;
                val[root] = v;
                return;
            }
            for(;o;){
                if(v == val[o]){
                    cnt[o]++, size[o]++;
                    splay(o, 0);
                    return;
                }
                bool b = v>val[o];
                if(!ch[o][b]){
                    ch[o][b] = ++num_node;
                    cnt[ch[o][b]] = size[ch[o][b]] = 1;
                    val[ch[o][b]] = v, fa[ch[o][b]] = o;
                    splay(ch[o][b], 0);
                    return;
                }
                o = ch[o][v>val[o]];
            }
        }
        inline void Find(int v){
            for(int o = root; o; o = ch[o][v>val[o]]){
                if(val[o] == v){ splay(o, 0); return; }
                if(!ch[o][v>val[o]]) return;
            }
        }
        inline void Delete(int v){
            Find(v);
            if(val[root] != v) return;
            int o = root;
            if(cnt[o] > 1){ --cnt[o],--size[o]; return; }
            if(!ch[o][0] && !ch[o][1]){ root = 0, fa[root] = 0; return; }
            if(!ch[o][0]){ root = ch[o][1], fa[root] = 0; return; }
            if(!ch[o][1]){ root = ch[o][0], fa[root] = 0; return; }
            int l_max = ch[root][0];
            while(ch[l_max][1]) l_max = ch[l_max][1];
            splay(l_max, root);
            ch[l_max][1] = ch[root][1];
            fa[ch[root][1]] = l_max;
            fa[l_max] = 0;
            int pre_root = root;
            root = l_max;
            clear(pre_root);
        }
        inline int Rnk(int x){
            Find(x);
            return size[ch[root][0]] + 1;
        }
        inline int Kth(int k){
            for(int o = root; o;){
                if(size[ch[o][0]] >= k) o = ch[o][0];
                else if(size[ch[o][0]] + cnt[o] < k){
                    k -= size[ch[o][0]] + cnt[o];
                    o = ch[o][1];
                }
                else{
                    splay(o,0);
                    return val[o];
                } 
            }
        }
        inline int Pre(int v){
            Insert(v);
            int o = ch[root][0];
            while(ch[o][1]) o = ch[o][1];
            int ans = val[o];
            Delete(v);
            return ans;
        }
        inline int Nxt(int v){
            Insert(v);
            int o = ch[root][1]; 
            while(ch[o][0]) o = ch[o][0];
            int ans = val[o]; 
            Delete(v);
            return ans;
        }
    }qxz;
    int main(){
    //    freopen(".in","r",stdin);
        n = read();
        for(int i = 1; i <= n; ++i){
            opt = read(), x = read();
            if(opt==1) qxz.Insert(x);
            if(opt==2) qxz.Delete(x);
            if(opt==3) printf("%d
    ",qxz.Rnk(x));
            if(opt==4) printf("%d
    ",qxz.Kth(x));
            if(opt==5) printf("%d
    ",qxz.Pre(x));
            if(opt==6) printf("%d
    ",qxz.Nxt(x));
        }
        return 0;
    }
  • 相关阅读:
    Part 3:视图和模板--Django从入门到精通系列教程
    Part 2:模型与后台管理admin站点--Django从入门到精通系列教程
    Part 1:请求与响应--Django从入门到精通系列教程
    java的static关键字
    接口
    final关键字
    抽象类
    动态绑定多态
    对象转型2
    对象转型1
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9365586.html
Copyright © 2011-2022 走看看