替罪羊树 ------ 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 word = getchar ();
    bool temp = false;
    for (now = 0; word < ‘0‘ || word > ‘9‘; word = getchar ())
        if (word == ‘-‘)
            temp = true;
    for (; word >= ‘0‘ && word <= ‘9‘; now = now * 10 + word - ‘0‘, word = getchar ());
    if (temp)
        now = -now;
}

const double alpha = 0.63;

int N;

struct G_D
{
    G_D *child[2];

    int key;
    int size, total;
    bool is_exist;

    inline void Up ()
    {
        this->size = this->child[0]->size + this->child[1]->size + is_exist;
        this->total = this->child[0]->total + this->child[1]->total + 1;
    }

    inline bool is_rebuild ()
    {
        return ((this->child[0]->total > this->total * alpha + 5) || (this->child[1]->total > this->total * alpha + 5));
    }
};

class Scapegoat_Tree_Type
{

    private :

        G_D poor_mem[Max_];
        G_D *Root, *Tail, *null;

        G_D *reuse[Max_];
        int Reuse_top;

        Inline G_D *New_Node (int key)
        {
            G_D *now = Reuse_top ? reuse[-- Reuse_top] : Tail ++;
            now->child[0] = now->child[1] = null;
            now->size = now->total = 1;
            now->is_exist = true;
            now->key = key;
            return now;
        }

        Inline void Travel (G_D *now, std :: vector <G_D *> &line)
        {
            if (now == null)
                return ;
            Travel (now->child[0], line);
            if (now->is_exist)
                line.push_back (now);
            else
                reuse[Reuse_top ++] = now;
            Travel (now->child[1], line);
        }

        Inline G_D *Divide (std :: vector <G_D *> &line, int l, int r)
        {
            if (l >= r)
                return null;
            int Mid = (l + r) >> 1;
            G_D *now = line[Mid];
            now->child[0] = Divide (line, l, Mid);
            now->child[1] = Divide (line, Mid + 1, r);
            now->Up ();
            return now;
        }

        Inline void Re_Build (G_D *&now)
        {
            static std :: vector <G_D *> line;
            line.clear ();
            Travel (now, line);
            now = Divide (line, 0, line.size ());
        }

        Inline G_D **Insert (G_D *&now, int key)
        {
            if (now == null)
            {
                now = New_Node (key);
                return &null;
            }
            else
            {
                now->size ++;
                now->total ++;
                G_D **res = Insert (now->child[key >= now->key], key);
                if (now->is_rebuild ())
                    res = &now;
                return res;
            }
        }

        Inline void Erase (G_D *now, int pos)
        {
            now->size --;
            int res = now->child[0]->size + now->is_exist;
            if (now->is_exist && pos == res)
            {
                now->is_exist = false;
                return ;
            }
            else
            {
                if (pos <= res)
                    Erase (now->child[0], pos);
                else
                    Erase (now->child[1], pos - res);
            }
        }

    public :

        Scapegoat_Tree_Type ()
        {
            Tail = poor_mem;
            null = Tail ++;
            null->child[0] = null->child[1] = null;
            null->total = null->size = null->key = 0;

            Root = null;
            Reuse_top = 0;
        }

        Inline void Insert (int key)
        {
            G_D **now = this->Insert (Root, key);
            if (*now != null)
                Re_Build (*now);
        }

        Inline int Get_Rank (int key)
        {
            G_D *now = Root;
            register int Answer = 1;
            for (; now != null; )
            {
                if (now->key >= key)
                    now = now->child[0];
                else
                {
                    Answer += now->child[0]->size + now->is_exist;
                    now = now->child[1];
                }
            }
            return Answer;
        }

        Inline int Get_kth_number (int k)
        {
            int Count = 0;
            for (G_D *now = Root; now != null; )
            {
                if (now->child[0]->size + 1 == k && now->is_exist)
                    return now->key;
                else if (now->child[0]->size >= k)
                    now = now->child[0];
                else
                {
                    k -= now->child[0]->size + now->is_exist;
                    now = now->child[1];
                }
            }
        }

        Inline  void Erase (int pos)
        {
            Erase (Root, Get_Rank (pos));
            if (Root->size < alpha * Root->total)
                Re_Build (Root);
        }

};

Scapegoat_Tree_Type Tree;

int M;
int main (int argc, char *argv[])
{

    read (M);

    for (int type, x; M --; )
    {
        read (type);
        read (x);

        switch (type)
        {
            case 1:
                Tree.Insert (x);
                break;
            case 2:
                Tree.Erase (x);
                break;
            case 3:
                printf ("%d\n", Tree.Get_Rank (x));
                break;
            case 4:
                printf ("%d\n", Tree.Get_kth_number (x));
                break;
            case 5:
                printf ("%d\n", Tree.Get_kth_number (Tree.Get_Rank (x) - 1));
                break;
            case 6:
                printf ("%d\n", Tree.Get_kth_number (Tree.Get_Rank (x + 1)));
                break;
        }
    }

    return 0;
}
时间: 2024-10-02 06:16:45

替罪羊树 ------ luogu 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各方面比较均衡,特别的伸展树在维护序列方面相对其它几种树优势

「BZOJ3600」没有人的算术 替罪羊树+线段树

题目描述 过长--不想发图也不想发文字,所以就发链接吧-- 没有人的算术 题解 \(orz\)神题一枚 我们考虑如果插入的数不是数对,而是普通的数,这就是一道傻题了--直接线段树一顿乱上就可以了. 于是我们现在只需要解决一个问题--维护这些数的大小关系. 由于这些数具有有序性,我们可以将这些数的值重记为一个数,这样就可以无脑地比较了.并且,由于这些值的大小可能会随着插入而更改,所以要用一棵平衡树来维护. 那么问题来了,这个数取什么值比较好呢? 首先当然可以是排名,不过如果使用排名,每次访问值的时

数组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) 近几天闲来无事...就把各种平衡树都写了一下... 下面是红黑树(Red Black Tree) #include <cstdio> #define Max 100001 #define Red true #define Black false #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (i

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 &

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #inc

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,替罪羊树

一.斜堆 斜堆是一种可以合并的堆 节点信息: struct Node { int v; Node *ch[2]; }; 主要利用merge函数 Node *merge(Node *x, Node *y) { if(!x) return y; if(!y) return x; if(x->v < y->v) swap(x, y); x->ch[1] = merge(x->ch[1], y); return swap(x->ch[0], x->ch[1]), x; }