LibreOJ #107. 维护全序集

Posted ZlycerQan

tags:

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

二次联通门 : LibreOJ #107. 维护全序集

 

 

 

/*
    LibreOJ #107. 维护全序集
    Splay
    支持 
    1.把 x 加入 S
    2.删除 S 中的一个 x,保证删除的 x 一定存在
    3.求 S 中第 k 小
    4.求 S 中有多少个元素小于 x
    5.求 S 中小于 x 的最大数
    6.求 S 中大于 x 的最小数

    我之前用Splay找数x的排名时采用的是挨个找的
    现在发现根本没必要
    只需要把splay(x)后减去右子树的大小与根节点的数出现几次即可 
*/
#include <cstdio>

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;
}


struct S_D 
{
    
    S_D *child[2], *father;
    
    int value;
    int weigth, size;
    
    S_D () 
    {
        child[0] = child[1] = NULL;
        father = NULL;
        value = 0;
        size = 1;
        weigth = 1;
    }
    
    inline int Get_Pos ()
    {
        return this->father->child[1] == this;
    }
    
    inline void Updata ()
    {
        this->size = this->weigth;
        if (this->child[0])
            this->size += this->child[0]->size;
        if (this->child[1])
            this->size += this->child[1]->size;
    }
    
    inline void Clear ()
    {
        child[0] = child[1] = NULL;
        father = NULL;
        value = size = weigth = 0;
    }
};

class Splay_Tree_Type
{
    
    private :
        
        S_D *Root;

        inline void Rotate (S_D *now)
        {
            S_D *Father = now->father;
            register int pos = now->Get_Pos () ^ 1;
            Father->child[pos ^ 1] = now->child[pos];
            if (now->child[pos])
                now->child[pos]->father = Father;
            if ((now->father = Father->father) != NULL)
                now->father->child[now->father->child[1] == Father] = now;
            Father->father = now;
            now->child[pos] = Father;

            Father->Updata ();
            now->Updata ();
            
            if (now->father == NULL)
                Root = now;
        }
        
        inline void Splay (S_D *now)
        {
            for (S_D *Father; Father = now->father; Rotate (now))
                if (Father->father)
                    Rotate (now->Get_Pos () == Father->Get_Pos () ? Father : now);
        }
        
    public :
        
        void Insert (int key)
        {
            if (Root == NULL)
            {
                Root = new S_D;
                Root->value = key;
                return ;
            }
            S_D *now = Root, *Father;
            for (; ;Father = now, now = now->child[key > now->value])
            {
                if (now == NULL)
                {
                    now = new S_D;
                    now->father = Father;
                    now->value = key;
                    Father->child[key > Father->value] = now;
                    Splay (now);
                    return ;
                }
                if (now->value == key)
                {
                    now->weigth ++;
                    Splay (now);
                    return ;
                }
            }
        }
        
        S_D *Find (int key)
        {
            S_D *now = Root;
            for (S_D *Father; (now != NULL && now->value != key); Father = now, now = now->child[key > now->value]);
            if (now == NULL)
                return now;
            Splay (now);
            return now;
        }
        
        int Find_Prifix (int key)
        {
            S_D *now = Find (key);
            bool flag = false;
            if (now == NULL)
            {
                this->Insert (key);
                now = Root;
                flag = true;
            }
            if (now->child[0] == NULL)
            {
                if (flag)
                    this->Delete (key);
                return -1;
            }
            for (now = now->child[0]; now->child[1]; now = now->child[1]);
            if (flag)
                this->Delete (key);
            return now->value;
        }
        
        S_D* Find_Prifix_pos (int key)
        {
            S_D *now = Find (key);
            bool flag = false;
            if (now == NULL)
            {
                this->Insert (key);
                now = Root;
                flag = true;
            }
            if (now->child[0] == NULL)
            {
                if (flag)
                    this->Delete (key);
                return NULL;
            }
            for (now = now->child[0]; now->child[1]; now = now->child[1]);
            if (flag)    
                this->Delete (key);
            return now;
        }
        
        int Find_Suffix (int key)
        {
            S_D *now = Find (key);
            bool flag = false;
            if (now == NULL)
            {
                this->Insert (key);
                now = Root;
                flag = true;
            }
            if (now->child[1] == NULL)
            {
                if (flag)
                    this->Delete (key);
                return -1;
            }
            for (now = now->child[1]; now->child[0]; now = now->child[0]);
            if (flag)
                this->Delete (key);
            return now->value;
        }
        
        int Get_rank (int key)
        {
            S_D *now = Find (key);
            bool flag = false;
            if (now == NULL)
            {
                this->Insert (key);
                flag = true;
            }
            int Answer = Root->size;
            if (Root->child[1])
                Answer -= Root->child[1]->size;
            Answer -= Root->weigth;
            if (flag)
                this->Delete (key);
            return Answer;
        }
        
        void Delete (int key)
        {
            S_D *now = Find (key);
            if (now->weigth > 1)
            {
                now->weigth --;
                now->size --;
                return ;
            }
            if (now->child[0] == NULL && now->child[1] == NULL)
            {
                now->Clear ();
                now = NULL; // ????could change to delete
                Root = NULL;
                return ;
            }
            if (now->child[0] == NULL)
            {
                S_D *res = now;
                Root = now->child[1];
                now->child[1]->father = NULL;
                now->Clear ();
                now = NULL;
                return ;
            }
            if (now->child[1] == NULL)
            {
                S_D *res = now;
                Root = now->child[0];
                now->child[0]->father = NULL;
                now->Clear ();
                now = NULL;
                return ;
            }
            
            S_D *res_pre = Find_Prifix_pos (now->value);
            S_D *res = Root;
            Splay (res_pre);
            
            Root->child[1] = res->child[1];
            res->child[1]->father = Root;
            res->Clear ();
            Root->Updata ();
        }
        
        int Get_kth_number (int key)
        {
            int Answer = 0;
            register int res;
            for (S_D *now = Root; ;)
            {
                if (now->child[0] && key <= now->child[0]->size)
                {
                    now = now->child[0];
                    continue;
                }
                res = (now->child[0] ? now->child[0]->size : 0) + now->weigth;
                if (key <= res)
                    return now->value;
                key -= res;
                now = now->child[1];
            }
        }
};

Splay_Tree_Type Splay;

int main (int argc, char *argv[])
{
    int N;
     read (N);
    int type, x;
    
    for (register int i = 1; i <= N; i ++)
    {
        read (type);
        read (x);
        switch (type)
        {
            case 0: 
            {
                Splay.Insert (x);
                break;
            }
            case 1:
            {
                Splay.Delete (x);
                break;
            }
            case 2:
            {
                printf ("%d\n", Splay.Get_kth_number (x));
                break;
            }
            case 3:
            {
                printf ("%d\n", Splay.Get_rank (x));
                break;
            }
            case 4:
            {
                printf ("%d\n", Splay.Find_Prifix (x)); 
                break;
            }
            case 5:
            {
                printf ("%d\n", Splay.Find_Suffix (x)); 
                break;
            }
        }
    }
    
    return 0;
}

 

以上是关于LibreOJ #107. 维护全序集的主要内容,如果未能解决你的问题,请参考以下文章

Dilworth定理证明

loj526「LibreOJ β Round #4」子集

省选模拟 19/10/11 (LibreOJ NOI Round #2)

loj516 「LibreOJ β Round #2」DP 一般看规律

LibreOJ #2013. 「SCOI2016」幸运数字

LibreOJ #113. 最大异或和