• 平衡树汇总


    一.Treap

    #include <bits/stdc++.h>
    using namespace std;
    const int SIZE = 100010;
    int INF = 0x7fffffff;
    
    int m, opt, x;
    int tot, root,  n;
    struct Treap
    {
        int l, r;
        int val, dat;
        int cnt, size; 
    }a[SIZE];
    
    int New(int val)
    {
        a[++tot].val = val;
        a[tot].dat = rand();
        a[tot].cnt = a[tot].size = 1;
        return tot;
    }
    
    void updata(int cur)
    {
        a[cur].size = a[a[cur].l].size + a[a[cur].r].size + a[cur].cnt;
    }
    
    void build()
    {
        New(-INF), New(INF);
        root = 1;
        a[1].r = 2;
        updata(root);
    }
    
    int GetRankByVal(int p, int val)
    {
        if(p == 0) return 0;
        if(val == a[p].val) return a[a[p].l].size + 1;
        if(val < a[p].val) return GetRankByVal(a[p].l, val);
        return GetRankByVal(a[p].r, val) + a[a[p].l].size + a[p].cnt;
    }
    
    int GetValByRank(int p, int rank)
    {
        if(p == 0) return INF;
        if(a[a[p].l].size >= rank) return GetValByRank(a[p].l, rank);
        if(a[a[p].l].size + a[p].cnt >= rank) return a[p].val ;
        return GetValByRank(a[p].r, rank - a[a[p].l].size - a[p].cnt);
    }
    
    void zig(int &p)
    {
        int q = a[p].l;
        a[p].l = a[q].r;
        a[q].r = p;
        p = q;
        updata(a[p].r), updata(p);
    }
    
    void zag(int &p)
    {
        int q = a[p].r;
        a[p].r = a[q].l;
        a[q].l = p;
        p = q;
        updata(a[p].l), updata(p);
    }
    
    void Insert(int &p, int val)
    {
        if(p == 0)
        {
            p = New(val);
            return;
        }
        if(val == a[p].val)
        {
            a[p].cnt++;
            updata(p);
            return;
        }
        if(val < a[p].val)
        {
            Insert(a[p].l, val);
            if(a[p].dat < a[a[p].l].dat) zig(p);
        }
        else 
        {
            Insert(a[p].r, val);
            if(a[p].dat < a[a[p].r].dat) zag(p);
        }
        updata(p);
    }
    
    int GetPre(int val)
    {
        int ans = 1;
        int p = root;
        while(p)
        {
            if(val == a[p].val)
            {
                if(a[p].l > 0)
                {
                    p = a[p].l;
                    while(a[p].r > 0) p = a[p].r;
                    ans = p;
                }
                break;
            }
            if(a[p].val < val && a[p].val > a[ans].val) ans = p;
            p = val < a[p].val ? a[p].l : a[p].r;
        }
        return a[ans].val;
    }
    
    int GetNext(int val)
    {
        int ans = 2;
        int p = root;
        while(p)
        {
            if(val == a[p].val)
            {
                if(a[p].r > 0)
                {
                    p = a[p].r;
                    while(a[p].l > 0) p = a[p].l;
                    ans = p;
                }
                break;
            }
            if(a[p].val > val && a[p].val < a[ans].val) ans = p;
            p = val < a[p].val ? a[p].l : a[p].r;
        }
        return a[ans].val;
    }
    
    void Remove(int &p, int val)
    {
        if(p == 0)return;
        if(val == a[p].val)
        {
            if(a[p].cnt > 1)
            {
                a[p].cnt--;
                updata(p);
                return;
            }
            if(a[p].l || a[p].r)
            {
                if(a[p].r == 0 || a[a[p].l].dat > a[a[p].r].dat)
                {
                    zig(p);
                    Remove(a[p].r, val);
                }
                else {
                    zag(p);
                    Remove(a[p].l, val);
                }
                updata(p);
            }
            else p = 0;
            return;
        }
        val < a[p].val ? Remove(a[p].l, val) : Remove(a[p].r, val);
        updata(p);
    }
    
    int main()
    {
        srand(time(0));
        build();
        cin>>m;
        while(m--)
        {
            scanf("%d%d",&opt,&x);
            switch(opt)
            {
                case 1:
                    Insert(root, x);
                    break;
                case 2:
                    Remove(root, x);
                    break;
                case 3:
                    printf("%d
    ",GetRankByVal(root, x) - 1);
                    break;
                case 4:
                    printf("%d
    ",GetValByRank(root, x + 1));
                    break;
                case 5:
                    printf("%d
    ",GetPre(x));
                    break;
                case 6:
                    printf("%d
    ",GetNext(x));
                    break;
            }
        }
        return 0;
        
    
        
    }
    zZhBr

    二.Splay

    #include <iostream>
    #include <cstdio> 
    #include <cstring>
    using namespace std;
    #define maxn 10000010
    #define inf 0x7f7f7f7f
    
    
    struct SplayTree
    {
        int ch[2], fa;
        int val, siz;
        int cnt;// 副本数 
    }t[maxn];
    
    int Root, tot;
    
    void pushup(int o)
    {
        t[o].siz = t[t[o].ch[0]].siz + t[t[o].ch[1]].siz + t[o].cnt;
    }
    
    void rotate(int x)
    {
        int y = t[x].fa, d = (t[y].ch[1] == x);
        t[ t[y].ch[d] = t[x].ch[d ^ 1] ].fa = y; // x 的儿子给 y ;   
        t[ t[x].fa = t[y].fa ].ch[ t[t[y].fa].ch[1] == y ] = x; // x 归为 y 的父亲的儿子 ; 
        t[ t[x].ch[d ^ 1] = y ].fa = x; // y 归为 x 的儿子; 
        pushup(y), pushup(x);
    }
    
    void Splay(int x, int f) // 把 x 旋转成 f 的儿子, 如果 f = 0, x 旋转到根节点: 
    {
        while(t[x].fa != f)
        {
            int y = t[x].fa, z = t[y].fa;
            if(z != f)
            {
                if ((t[z].ch[0] == y) == (t[y].ch[0] == x)) {
                rotate(y);
                } else {
                    rotate(x);
                }
                //rotate( (t[z].ch[0] == y) == (t[y].ch[0] == x) ? y : x);// x 与 y 为同一边子树 旋转 y, 否则旋转 x; 
            }
            rotate(x);
        }
        pushup(x);
        if(f == 0) Root = x;
    }
    
    void insert(int v)
    {
        int o = Root, u = 0;
        while(o && t[o].val != v)
        {
            u = o;
            int d = t[o].val < v;
            o = t[o].ch[d];
        }
        if(o)
        {
            t[o].cnt ++;
            pushup(o);
        }
        else
        {
            o = ++tot;
            if (u) 
            {
                int d = t[u].val < v;
                t[u].ch[d] = o;
            }
            t[o].fa = u;
            t[o].val = v;//cout<<t[o].val<<endl;
            t[o].siz = 1;
            t[o].cnt = 1;
            t[o].ch[1] = t[o].ch[0] = 0;
        }
        Splay(o, 0);
    }
    
    int K_th(int k)
    {
        int o = Root;
        if(t[o].siz < k)
        {
            return 0;
        }
        while(1)
        {
            if(k > t[t[o].ch[0]].siz + t[o].cnt)
            {
                k -= t[t[o].ch[0]].siz + t[o].cnt;
                o = t[o].ch[1];
            }
            else
            
                if(t[t[o].ch[0]].siz >= k)
                {
                    o = t[o].ch[0];
                }
                else
                {
                    break;
                }
            
        }
        Splay(o, 0);
        return t[o].val;
            
    }
    
    void Find(int x)
    {
        int o = Root;
        if(!o) return ;
    /*    while(1)
        {
            if(t[o].val == x)
            {
                Splay(o, 0);
                return ;
            }
            int d = t[o].val < x;
            if(!t[o].ch[o]) return ;
            o = t[o].ch[o];
        }*/
        while(t[o].ch[t[o].val < x] and x != t[o].val)
        {
            o = t[o].ch[t[o].val < x];
        }
        Splay(o, 0);
    }
    
    int Next(int x, int d)
    {
        Find(x);
        int o = Root;
        if( (t[o].val > x and d) or (t[o].val < x and !d)) return o;
        o = t[o].ch[d];
        while(t[o].ch[d ^ 1]) o = t[o].ch[d ^ 1];
        return o;
    }
    
    void Del(int x)
    {
        int lst = Next(x, 0);
        int nxt = Next(x, 1);
        Splay(lst, 0);Splay(nxt, lst);
        int del = t[nxt].ch[0];
        if(t[del].cnt > 1) 
        {
            t[del].cnt --;
            Splay(del, 0);
        }
        else t[nxt].ch[0] = 0;
    }
    
    int main()
    {
        insert(inf);
        insert(-inf);
        int n;
        cin >> n;
        while(n--)
        {
            int opt, x;
            scanf("%d%d", &opt, &x);
            if(opt == 1)
            {
                insert(x);
            }
            else if(opt == 2)
            {
                Del(x);
            }
            else if(opt == 3)
            {
                Find(x);
                printf("%d
    ", t[t[Root].ch[0]].siz);
            }
            else if(opt == 4)
            {
                printf("%d
    ", K_th(x + 1));
            }
            else if(opt == 5)
            {
                printf("%d
    ", t[Next(x, 0)].val);
            }
            else
            {
                printf("%d
    ", t[Next(x, 1)].val);
            }
        }
        return 0;    
    }
    zZhBr

     

    三.无旋Treap

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    #define maxn 500005
    
    struct FHQ_Treap
    {
        int ch[2];
        int val, pri;
        int siz, cnt;
    }t[maxn];
    
    int tot, Root;
    
    int newnode(int v)
    {
        tot++;
        t[tot].ch[1] = t[tot].ch[2] = 0;
        t[tot].cnt = t[tot].siz = 1;
        t[tot].val = v;
        t[tot].pri = rand();
        return tot;
    }
    
    void pushup(int o)
    {
        t[o].siz = t[t[o].ch[1]].siz + t[t[o].ch[0]].siz + t[o].cnt;
    }
    
    int Merge(int x, int y)
    {
        if(!x or !y) return x + y;
        if(t[x].pri < t[y].pri)
        {
            t[x].ch[1] = Merge(t[x].ch[1], y);
            pushup(x);
            return x;
        }
        else
        {
            t[y].ch[0] = Merge(x, t[y].ch[0]);
            pushup(y);
            return y;
        }
    }
    
    #define par pair<int, int>
    #define m_p make_pair
    #define fi first
    #define se second
    
    par Split1(int o, int k) // 按排名切 
    {
        if(!o or !k) return m_p(0, o);
        int d = t[t[o].ch[0]].siz;
        par res;
        if(k <= d)
        {
            res = Split1(t[o].ch[0], k);
            t[o].ch[0] = res.second;
            pushup(o);
            res.second = o;
        }
        else
        {
            res = Split1(t[o].ch[1], k - d - 1);
            t[o].ch[1] = res.first;
            pushup(o);
            res.first = o;
        }
        return res;
    }
    
    void Split2(int o, int k, int &x, int &y) // 按价值切
    {
        if(!o) x = y = 0;
        else
        {
            if(t[o].val <= k)
            {
                x = o;
                Split2(t[o].ch[1], k, t[o].ch[1], y);
            }
            else
            {
                y = o;
                Split2(t[o].ch[0], k, x, t[o].ch[0]);
            }
            pushup(o);
        }
    } 
    
    int K_th(int o, int k)
    {
        while(1)
        {
            if(k <= t[t[o].ch[0]].siz)
            {
                o = t[o].ch[0];
            }
            else if(k == t[t[o].ch[0]].siz + t[o].cnt)
            {
                return o;
            }
            else 
            {
                k -= t[t[o].ch[0]].siz + t[o].cnt;
                o = t[o].ch[1];
            }
        }
    }
    
    int main()
    {
        srand(time(0));
        int n;
        cin >> n;
        while(n--)
        {
            int opt, a;
            scanf("%d%d", &opt, &a);
            int x, y, z;
            if(opt == 1)
            {
                Split2(Root, a, x, y);
                Root = Merge(Merge(x, newnode(a)), y);
            }
            else if(opt == 2)
            {
                Split2(Root, a, x, z);
                Split2(x, a - 1, x, y);
                y = Merge(t[y].ch[0], t[y].ch[1]);
                Root = Merge(Merge(x, y), z);
            }
            else if(opt == 3)
            {
                Split2(Root, a - 1, x, y);
                printf("%d
    ", t[x].siz + t[x].cnt);
                Root = Merge(x, y);
            }
            else if(opt == 4)
            {
                printf("%d
    ", t[K_th(Root, a)].val);
            }
            else if(opt == 5)
            {
                Split2(Root, a - 1, x, y);
                printf("%d
    ", t[K_th(x, t[x].siz)].val);
                Root = Merge(x, y);
            }
            else
            {
                Split2(Root, a, x, y);
                printf("%d
    ", t[K_th(y, 1)].val);
                Root = Merge(x, y);
            }
        }
        return 0;
    }
    zZhBr
  • 相关阅读:
    Linux下守护进程的编程实现(转)
    gcc 中-I、 -L 与-l选项的作用
    va_list 、va_start、 va_arg、 va_end 使用说明
    sizeof('a')在C与C++中的区别
    Qt主要类简介
    linux命令
    linux文件编程
    linux一些基本命令
    Linux主机SSH免密设置解析
    javaweb添加拦截器
  • 原文地址:https://www.cnblogs.com/BriMon/p/8975152.html
Copyright © 2020-2023  润新知