Splay模板

Posted zzh-brim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Splay模板相关的知识,希望对你有一定的参考价值。

并没有写序列翻转的板子;

【模板】普通平衡树(Treap/SBT)

 

技术分享图片
#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

 

以上是关于Splay模板的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1588 splay模板题

P3369 模板普通平衡树 题解(Splay)

[模板]洛谷T2042 NOI2005 维护数列 Splay

[模板]洛谷T3380 二逼平衡树 线段树套Splay

「Splay」指针版与数组版模板

[模板]洛谷T3391 文艺平衡树 链表&递归版无父指针版Splay