洛谷 P3369 模板普通平衡树(Treap/SBT)

Posted xgzc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3369 模板普通平衡树(Treap/SBT)相关的知识,希望对你有一定的参考价值。

题目描述


您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入x数
  2. 删除x数(若有多个相同的数,因只删除一个)
  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
  4. 查询排名为x的数
  5. 求x的前驱(前驱定义为小于x,且最大的数)
  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1≤opt≤6)

输出格式:

对于操作3,4,5,6每行输出一个数,表示对应答案

输入输出样例

输入样例:

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

输出样例:

106465
84185
492737

Splay 解析尚未完成 参见yyb dalao的博客

丑陋的代码送上(yyb大佬的代码比我的漂亮多了):

#ifndef SPLAY_TREE_HPP
#define SPLAY_TREE_HPP
#include<bits/stdc++.h>
using namespace std;
namespace Splay_tree
{
    template<typename T>
    struct splay_node
    {
        T value;
        int size;
        int cnt;
        bool reverse;
        splay_node *father;
        splay_node *son[2];
        splay_node(){}
        splay_node(T v, splay_node *f=NULL)
            :value(v),cnt(1)
        {
            father=f;
            size=0;
            son[0]=son[1]=NULL;
        }
    };

    template<typename T, typename C=less<T> >
    class Splay
    {
        private:
            typedef splay_node<T> node;
            node *root;
            C small_to;
            bool big_to(T x, T y){return small_to(y,x);}
            bool equal_to(T x, T y){return !(small_to(x,y)||big_to(x,y));}

            inline bool son(node *f, node *s)
            {
                return f->son[1]==s;
            }
            inline void rotate(node *t)
            {
                node *f = t->father;
                node *g = f->father;
                bool a = son(f, t), b = !a;
                f->son[a] = t->son[b];
                if (t->son[b] != NULL)
                    t->son[b]->father = f;
                t->son[b] = f;
                f->father = t;
                t->father = g;
                if (g != NULL)
                    g->son[son(g, f)] = t;
                else
                    root = t;
                update(f);
                update(t);
            }

            inline void splay(node *t, node *p)
            {
                while (t->father != p)
                {
                    node *f = t->father;
                    node *g = f->father;
                    if (g == p)
                        rotate(t);
                    else
                    {
                        if (son(g, f) ^ son(f, t)) rotate(t), rotate(t);
                        else rotate(f), rotate(t);
                    }
                }
                update(t);
            }

            inline T k_th(int k, node *f)
            {
                int tmp;
                node *t=root;
                while(1)
                {
                    int tmp=size(t->son[0])+t->cnt;
                    int sze=tmp-t->cnt;
                    if(k<=tmp&&sze<k) break;
                    else if(k<=sze) t=t->son[0];
                    else k-=tmp,t=t->son[1];
                }
                T ans=t->value;
                return ans;
            }
            
            inline node* insert(T val, node *t)
            {
                int b=big_to(val,t->value);
                if(equal_to(val,t->value))
                {
                    t->cnt++;
                    update(t);
                    return t;
                }
                if(t->son[b]==NULL)
                {
                    t->son[b]=new node(val,t);
                    update(t->son[b]);
                    update(t);
                    return t->son[b];
                }
                else
                {
                    node *ans=insert(val,t->son[b]);
                    update(t);
                    return ans;
                }
            }

        public:
            Splay()
            {
                root=NULL;
            }
            
            inline void insert(T val)
            {
                if (root == NULL)
                {
                    root = new node(val, NULL);
                    update(root);
                    return;
                }
                else
                {
                    node *t = insert(val,root);
                    splay(t,NULL);
                }
            }

            inline void erase(T val)
            {
                node *t = root;
                while(t)
                {
                    if (equal_to(t->value,val))
                        break;
                    t = t->son[big_to(val,t->value)];
                }
                if (t != NULL)
                {
                    splay(t, NULL);
                    if(t->cnt>1)
                    {
                        t->cnt--;
                        update(t);
                        return;
                    }
                    if (t->son[0] == NULL)
                    {
                        root = t->son[1];
                        if (root != NULL)
                        {
                            root->father = NULL;
                            update(root);
                        }
                    }
                    else
                    {
                        node *p = t->son[0];
                        while (p->son[1] != NULL)
                            p = p->son[1];
                        splay(p, t); root = p;
                        root->father = NULL;
                        p->son[1] = t->son[1];
                        update(p);
                        if (p->son[1] != NULL)
                            p->son[1]->father = p;
                    }
                }
            }

            inline T pre(T val)
            {
                T ans=pre_ptr(val)->value;
                return ans;
            }

            inline T suc(T val)
            {
                node *x = root;
                insert(val);
                node *t=root->son[1];
                if(t==NULL) return T(NULL);
                while(t->son[0]!=NULL) t=t->son[0];
                erase(val);
                T ans=t->value;
                return ans;
            }

            inline T max_value()
            {
                node *t=root;
                while(t->son[1]!=NULL) t=t->son[1];
                return t->value;
            }

            inline T min_value()
            {
                node *t=root;
                while(t->son[0]!=NULL) t=t->son[0];
                return t->value;
            }

            inline T k_th(int k)
            {
                return k_th(k,NULL);
            }
            
            inline int rank(T val)
            {
                node *t=root;
                while(!equal_to(t->value, val))
                    t=t->son[big_to(val,t->value)];
                splay(t,NULL);
                return size(t->son[0])+1;
            }
            
            inline void print()
            {
                print(root);
                puts("");
            }

        private:
        
            inline node* pre_ptr(T val)
            {
                insert(val);
                node *t=root->son[0];
                if(t==NULL) return NULL;
                while(t->son[1]!=NULL) t=t->son[1];
                erase(val);
                return t;
            }
        
            inline void print(node *t)
            {
                if(t==NULL) return;
                print(t->son[0]);
                printf("%d ",t->value);
                print(t->son[1]);
            }
            
            inline int size(node *t)
            {
                return t == NULL ? 0 : t->size;
            }

            inline void update(node *t)
            {
                t->size = t->cnt;
                t->size += size(t->son[0]);
                t->size += size(t->son[1]);
            }
    };
}
#endif

int main()
{
    using namespace Splay_tree;
    int n;
    Splay<int> tree;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int ops;
        int x;
        scanf("%d%d",&ops,&x);
        switch(ops)
        {
            case 1:
                tree.insert(x);
                break;
            case 2:
                tree.erase(x);
                break;
            case 3:
            {
                int t=tree.rank(x);
                printf("%d\\n",t);
                break;
            }
            case 4:
            {
                int y=tree.k_th(x);
                printf("%d\\n",y);
                break;
            }
            case 5:
                printf("%d\\n",tree.pre(x));
                break;
            case 6:
                int t=tree.suc(x);
                printf("%d\\n",t);
                break;
        }
    }
}
View Code

 

以上是关于洛谷 P3369 模板普通平衡树(Treap/SBT)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P3369 模板普通平衡树(STL做法:vector&multiset)

洛谷 P3369 BZOJ 3224 模板普通平衡树(Treap/SBT)

洛谷P3369普通平衡树(splay)

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

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

P3369 模板普通平衡树FHQtreap