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

二次联通门 : P3369 【模板】普通平衡树(Treap/SBT)

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

    splay 模板

    支持插入x数
    删除x数(若有多个相同的数,因只删除一个)
    查询x数的排名(若有多个相同的数,因输出最小的排名)
    查询排名为x的数
    求x的前驱(前驱定义为小于x,且最大的数)
    求x的后继(后继定义为大于x,且最小的数) 

*/
#include <cstdio>

#define Max 200005

void read (int &now)
{
    now = 0;
    register char word = getchar ();
    bool temp = false;
    while (word < ‘0‘ || word > ‘9‘)
    {
        if (word == ‘-‘)
            temp = true;
        word = getchar ();
    }
    while (word <= ‘9‘ && word >= ‘0‘)
    {
        now = now * 10 + word - ‘0‘;
        word = getchar ();
    }
    if (temp)
        now = -now;
}

class Splay_Tree_Type
{
    private:

        struct Tree_Date
        {
            int weigth;
            int size;
            int key;
            int child[2];
            int father;
        }
        tree[Max];

        inline int Get_Son (int now)
        {
            return tree[tree[now].father].child[1] == now;
        }

        int Count;
        int Root;

    public :

        inline void Update (int now)
        {
            tree[now].size = tree[now].weigth;
            if (tree[now].child[0])
                tree[now].size += tree[tree[now].child[0]].size;
            if (tree[now].child[1])
                tree[now].size += tree[tree[now].child[1]].size;
        }

        inline void Rotate (int now)
        {
            int father = tree[now].father;
            int Grand = tree[father].father;
            int pos = Get_Son (now);
            tree[father].child[pos] = tree[now].child[pos ^ 1];
            tree[tree[father].child[pos]].father = father;
            tree[now].child[pos ^ 1] = father;
            tree[father].father = now;
            tree[now].father = Grand;
            if (Grand)
                tree[Grand].child[tree[Grand].child[1] == father] = now;
            Update (father);
            Update (now);
        }

        void Splay (int now)
        {
            for (int father; father = tree[now].father; Rotate (now))
                if (tree[father].father)
                    Rotate (Get_Son (now) == Get_Son (father) ? father : now);
            Root = now;
        }

        int Find_Prefix ()
        {
            int now = tree[Root].child[0];
            while (tree[now].child[1])
                now = tree[now].child[1];
            return now;
        }

        int Find_Suffix ()
        {
            int now = tree[Root].child[1];
            while (tree[now].child[0])
                now = tree[now].child[0];
            return now;
        }

        inline void Clear (int now)
        {
            tree[now].child[1] = 0;
            tree[now].child[1] = 1;
            tree[now].size = 0;
            tree[now].weigth = 0;
            tree[now].key = 0;
            tree[now].father = 0;
        }

        int Find_x_rank (int x)
        {
            int now = Root;
            int Answer = 0;
            while (true)
            {
                if (x < tree[now].key)
                {
                    now = tree[now].child[0];
                    continue;
                }
                Answer += tree[now].child[0] ? tree[tree[now].child[0]].size : 0;
                if (tree[now].key == x)
                {
                    Splay (now);
                    return Answer + 1;
                }
                Answer += tree[now].weigth;
                now = tree[now].child[1];
            }
        }

        int Find_rank_x (int x)
        {
            int now = Root;
            while (true)
            {
                if (tree[now].child[0] && x <= tree[tree[now].child[0]].size)
                {
                    now = tree[now].child[0];
                    continue;
                }
                int temp = (tree[now].child[0] ? tree[tree[now].child[0]].size : 0) + tree[now].weigth;
                if (x <= temp)
                    return tree[now].key;
                x -= temp;
                now = tree[now].child[1];
            }
        }

        void Insert (int x)
        {
            if (!Root)
            {
                Count++;
                tree[Count].key = x;
                tree[Count].size = 1;
                tree[Count].weigth = 1;
                Root = Count;
                return;
            }
            int father = 0, now = Root;
            while (true)
            {
                if (tree[now].key == x)
                {
                    tree[now].size++;
                    tree[now].weigth++;
                    Splay (now);
                    return ;
                }
                father = now;
                now = tree[now].child[x > tree[father].key];
                if (!now)
                {
                    Count++;
                    tree[father].child[x > tree[father].key] = Count;
                    tree[Count].father = father;
                    tree[Count].key = x;
                    tree[Count].size = 1;
                    tree[Count].weigth = 1;
                    Splay (Count);
                    return ;
                }
            }
        }

        void Delete (int x)
        {
            Find_x_rank (x);
            if (tree[Root].weigth > 1)
            {
                tree[Root].weigth--;
                tree[Root].size--;
                return ;
            }
            if (!tree[Root].child[0] && !tree[Root].child[1])
            {
                Clear (Root);
                Root = 0;
                return ;
            }
            if (!tree[Root].child[0])
            {
                int temp = Root;
                Root = tree[Root].child[1];
                tree[Root].father = 0;
                Clear (temp);
                return ;
            }
            if (!tree[Root].child[1])
            {
                int temp = Root;
                Root = tree[Root].child[0];
                tree[Root].father = 0;
                Clear (temp);
                return ;
            }
            int Prefix = Find_Prefix ();
            int temp = Root;
            Splay (Prefix);
            tree[Root].child[1] = tree[temp].child[1];
            tree[tree[temp].child[1]].father = Root;
            Clear (temp);
            Update (Root);
        }

        inline int Get_tree_value (int now)
        {
            return tree[now].key;
        }
};

Splay_Tree_Type Splay_Tree;

int main (int argc, char *argv[])
{
    int N;
    read (N);
    int type, x;
    for (; N--; )
    {
        read (type);
        read (x);
        if (type == 1)
            Splay_Tree.Insert (x);
        else if (type == 2)
            Splay_Tree.Delete (x);
        else if (type == 3)
            printf ("%d\n", Splay_Tree.Find_x_rank (x));
        else if (type == 4)
            printf ("%d\n", Splay_Tree.Find_rank_x (x));
        else if (type == 5)  // 因为不确定x是否在平衡树中, 那么先插入在查找可以防止这种情况的发生
        {
            Splay_Tree.Insert (x);
            printf ("%d\n", Splay_Tree.Get_tree_value (Splay_Tree.Find_Prefix ()));
            Splay_Tree.Delete (x);
        }
        else
        {
            Splay_Tree.Insert (x);
            printf ("%d\n", Splay_Tree.Get_tree_value (Splay_Tree.Find_Suffix ()));
            Splay_Tree.Delete (x);
        }
    }
    return 0;
}
时间: 2024-10-13 01:48:10

P3369 【模板】普通平衡树(Treap/SBT)的相关文章

luoguP3369[模板]普通平衡树(Treap/SBT) 题解

链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #incl

各种平衡树Treap/SBT/Avl/Splay tree

看了这么久的平衡树,是时候做个总结了. 以poj 3481为例,敲了四份代码,分别是Treap ,Size Balance Tree,Avl Tree,splay tree. 唯独少了红黑树T_T... 总的来说每种平衡树各有各的优点吧: Treap写起来简单上手也快如果熟练的话不到十分种可以敲完. SBT速度快名不虚传... Avl树高度平衡吧,不过实际的效果不尽如人意,可能是我实现的姿势不对吧/(ㄒoㄒ)/~~ splay tree各方面比较均衡,特别的伸展树在维护序列方面相对其它几种树优势

数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { now = 0; register char word = getchar (); bool temp = false; while (wor

替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 闲的没事,把各种平衡树都写写 比较比较... 下面是替罪羊树 #include <cstdio> #include <vector> #define Max_ 100010 #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { register char w

红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 近几天闲来无事...就把各种平衡树都写了一下... 下面是红黑树(Red Black Tree) #include <cstdio> #define Max 100001 #define Red true #define Black false #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (i

AC日记——【模板】普通平衡树(Treap/SBT) 洛谷 P3369

[模板]普通平衡树(Treap/SBT) 思路: 劳资敲了一个多星期: 劳资终于a了: 劳资一直不a是因为一个小错误: 劳资最后看的模板: 劳资现在很愤怒: 劳资不想谈思路!!! 来,上代码: #include <cstdio> using namespace std; #define maxn 1000005 struct SplayTreeNodeType { int w,key,opi,size,ch[2]; }; struct SplayTreeNodeType tree[maxn];

算法模板——平衡树Treap 2

实现功能:同平衡树Treap 1(BZOJ3224 / tyvj1728) 这次的模板有了不少的改进,显然更加美观了,几乎每个部分都有了不少简化,尤其是删除部分,这个参照了hzwer神犇的写法,在此鸣谢,然后,贴模板走人 1 var 2 i,j,k,l,m,n,head,tot:longint; 3 a,b,lef,rig,fix:array[0..100010] of longint; 4 function min(x,y:longint):longint; 5 begin 6 if x<y

hiho 1325 : 平衡树&#183;Treap

#1325 : 平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? 小Ho:就是二叉排序树和堆啊,你看这两种数据结构都是构造了一个二叉树,一个节点有一个父亲和两个儿子. 如果用1..n的数组来存储的话,对于二叉树上的一个编号为k的节点,其父亲节点刚好是k/2.并且它的两个儿子节点分别为k*2和k*2+1,计算起来非常方便呢. 小Hi:没错,但是小Hi你知道有一种办

平衡树 Treap

//平衡树 Treap //维护一个堆使得随机权值小(大)的数始终在上方 //使用随机权值目的:防止出题人卡 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; struct uio{ int l,r,siz,num,rd,tim;