LibreOJ #107. 维护全序集

Posted

tags:

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

                        内存限制:256 MiB 时间限制:1000 ms 标准输入输出
                            题目类型:传统 评测方式:文本比较
                                上传者: 匿名
 

 

 

splay模板题 

屠龙宝刀点击就送

#include <cstdio>
typedef long long LL;
#define N 300500

LL data[N];
int siz[N],cnt[N],ch[N][2],fa[N],root,cn,n;
inline int son(int x) {return ch[fa[x]][1]==x;}
inline void pushup(int rt)
{
    int l=ch[rt][0],r=ch[rt][1];
    siz[rt]=cnt[rt]+siz[l]+siz[r];
}
inline void rotate(int x)
{
    int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
    if(z) ch[z][c]=x;
    else root=x;
    fa[x]=z;
    if(a) fa[a]=y;
    ch[y][b]=a;
    ch[x][!b]=y;
    fa[y]=x;
    pushup(y);
    pushup(x);
}
void splay(int x,int i)
{
    for(;fa[x]!=i;)
    {
        int y=fa[x],z=fa[y];
        if(z==i) rotate(x);
        else 
        {
            if(son(x)==son(y))
            {
                rotate(y);
                rotate(x);
            }
            else
            {
                rotate(x);
                rotate(x);
            }
        }
    }
}
void ins(int &rt,LL x)
{
    if(!rt)
    {
        rt=++cn;
        data[cn]=x;
        siz[cn]=cnt[cn]=1;
        splay(cn,0);
        return;
    }
    if(data[rt]==x)
    {
        cnt[rt]++;
        siz[rt]++;
        splay(rt,0);
        return;
    }
    if(x<data[rt])
    {
        ins(ch[rt][0],x);
        fa[ch[rt][0]]=rt;
        pushup(rt);
    }
    else 
    {
        ins(ch[rt][1],x);
        fa[ch[rt][1]]=rt;
        pushup(rt);
    }
}
int getmn(int rt)
{
    int p=rt,ans=-1;
    for(;p;p=ch[p][0]) ans=p;
    return ans;
}
void del(int rt,LL x)
{
    if(data[rt]==x)
    {
        if(cnt[rt]>1)
        {
            cnt[rt]--;
            siz[rt]--;
        }
        else
        {
            splay(rt,0);
            int p=getmn(ch[rt][1]);
            if(p!=-1)
            {
                splay(p,rt);
                root=p;
                fa[p]=0;
                ch[p][0]=ch[rt][0];
                fa[ch[rt][0]]=p;
            }
            else
            {
                root=ch[rt][0];
                fa[ch[rt][0]]=0;
            }
        }
        return;
    }
    if(x<data[rt])
    {
        del(ch[rt][0],x);
        pushup(rt);
    }
    else
    {
        del(ch[rt][1],x);
        pushup(rt);
    }
}
int getkth(int rt,int k)
{
    int l=ch[rt][0];
    if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return rt;
    if(siz[l]+1>k) return getkth(ch[rt][0],k);
    else if(k>siz[l]+cnt[rt]) return getkth(ch[rt][1],k-(siz[l]+cnt[rt])); 
}
int get_suc(int rt,LL x)
{
    int p=rt,ret=-1;
    for(;p;)
    {
        if(x>=data[p]) p=ch[p][1];
        else 
        {
            ret=p;
            p=ch[p][0];
        }
    }
    return ret;
}
int get_pre(int rt,LL x)
{
    int p=rt,ret=-1;
    for(;p;)
    {
        if(x<=data[p]) p=ch[p][0];
        else
        {
            ret=p;
            p=ch[p][1];
        }
    }
    return ret;
}
int get_pos(int rt,LL x)
{
    if(data[rt]==x) return rt;
    if(x<data[rt]) return get_pos(ch[rt][0],x);
    else return get_pos(ch[rt][1],x);
}
int Main()
{
    scanf("%d",&n);
    for(LL opt,x,pos,flag;n--;)
    {
        scanf("%lld%lld",&opt,&x);
        if(!opt) ins(root,x);
        else if(opt==1) del(root,x);
        else if(opt==2) printf("%lld\\n",data[getkth(root,x)]);
        else if(opt==3) ins(root,x),pos=get_pos(root,x),splay(pos,0),printf("%d\\n",siz[ch[root][0]]),del(root,x); 
        else if(opt==4) pos=get_pre(root,x),pos==-1?printf("-1\\n"):printf("%lld\\n",data[pos]);
        else pos=get_suc(root,x),pos==-1?printf("-1\\n"):printf("%lld\\n",data[pos]);
    }
    return 0;
}
int sb=Main();
int main(int argc,char *argv[]) {;}

 

 

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

Dilworth定理证明

loj526「LibreOJ β Round #4」子集

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

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

LibreOJ #2013. 「SCOI2016」幸运数字

LibreOJ #113. 最大异或和