平衡树汇总

一.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\n",GetRankByVal(root, x) - 1);
                break;
            case 4:
                printf("%d\n",GetValByRank(root, x + 1));
                break;
            case 5:
                printf("%d\n",GetPre(x));
                break;
            case 6:
                printf("%d\n",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\n", t[t[Root].ch[0]].siz);
        }
        else if(opt == 4)
        {
            printf("%d\n", K_th(x + 1));
        }
        else if(opt == 5)
        {
            printf("%d\n", t[Next(x, 0)].val);
        }
        else
        {
            printf("%d\n", 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\n", t[x].siz + t[x].cnt);
            Root = Merge(x, y);
        }
        else if(opt == 4)
        {
            printf("%d\n", t[K_th(Root, a)].val);
        }
        else if(opt == 5)
        {
            Split2(Root, a - 1, x, y);
            printf("%d\n", t[K_th(x, t[x].siz)].val);
            Root = Merge(x, y);
        }
        else
        {
            Split2(Root, a, x, y);
            printf("%d\n", t[K_th(y, 1)].val);
            Root = Merge(x, y);
        }
    }
    return 0;
}
zZhBr

猜你喜欢

转载自www.cnblogs.com/zZh-Brim/p/8975152.html