zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj4825:loj2018:p3721:[HNOI2017]单旋

    题目大意

    spaly是一种数据结构,它是只有单旋的splay
    有一个初始为空的spaly,(m)((mleq10^5))次操作,每个操作是以下5种中的一种:
    1.向spaly中插入一个数(过程和treap的插入类似,只不过插入之后不会调整),并询问这个数的深度
    2.询问最小值的深度,并将它splay到根
    3.询问最大值的深度,并将它splay到根
    4.询问最小值的深度,将它splay到根并把它删掉
    5.询问最大值的深度,将它splay到根并把它删掉

    题解

    直接维护spaly的话,spaly不一定平衡,“从一个根走到一个点”和“把一个点旋转到根”的复杂度会很大
    对于1操作,发现新插入的数的父亲一定是它的前驱或者后继中深度更大的那个,直接把它接过去,并把它的深度置为父亲的深度+1就行
    对于2,3,4,5操作,发现被splay的点只可能是最小或最大的点
    在把最小值或最大值转到根时,会发现只要把它的儿子接到它的父亲、把原来的根接到它就可以
    在这个过程中,要把它子树外的点深度+1,如果还要删掉它的话就把所有点深度-1
    用splay维护前驱后继、最大值最小值、区间加单点查询

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>0
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define maxn 100010
    #define inf 2147483647
    #define ls son[u][0]
    #define rs son[u][1]
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x==0){putchar('0'),putchar('
    ');return;}
        int f=0;char ch[20];
        if(x<0)putchar('-'),x=-x;
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
        return;
    }
    int dep[maxn],son[maxn][2],fa[maxn],key[maxn],mk[maxn],rt;
    int fakefa[maxn],fakeson[maxn][2],fakert,n,cnt; 
    void mark(int u,int k){if(u)dep[u]+=k,mk[u]+=k;}
    void pd(int u){if(mk[u]&&u)mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}
    int getso(int u){return son[fa[u]][0]!=u;}
    int newnd(int k,int f){int u=++cnt;ls=rs=0,key[u]=k,fa[u]=f;return u;}
    void rot(int u)
    {
        int fu=fa[u],ffu=fa[fu],l=getso(u),fl=getso(fu),r=l^1,rson=son[u][r];
        fa[rson]=fu,fa[u]=ffu,fa[fu]=u,son[u][r]=fu,son[fu][l]=rson,son[ffu][fl]=u;
    }
    void splay(int u,int k)
    {
        pd(u);while(fa[u]!=k){if(mk[fa[u]])cout<<"nooo"<<endl;if(fa[fa[u]]!=k)rot(getso(u)^getso(fa[u])?u:fa[u]);rot(u);}
        if(!k)rt=u;
    }
    void fnd(int k)
    {
        int u=rt;
        while(key[u]!=k&&son[u][key[u]<k])pd(u),u=son[u][key[u]<k];
        splay(u,0); 
    }
    int nxt(int k,int f)
    {
        fnd(k);int u=rt;
        if((key[u]<k&&!f)||(key[u]>k&&f))return u;
        pd(u),u=son[u][f];
        while(u&&son[u][f^1])pd(u),u=son[u][f^1];
        return u;
    }
    void ins(int k)
    {
        int lk=nxt(k,0),rk=nxt(k,1),mxk=dep[lk]>dep[rk]?lk:rk;
        splay(lk,0),splay(rk,lk);
        son[rk][0]=newnd(k,rk),dep[cnt]=dep[mxk]+1;
        if(mxk<=2)fakert=cnt;
        else fakeson[mxk][key[mxk]<k?1:0]=cnt,fakefa[cnt]=mxk;
    }
    void del(int k)
    {
        int lk=nxt(k,0),rk=nxt(k,1);
        splay(lk,0),splay(rk,lk);
        son[rk][0]=0;
    }
    void add(int l,int r,int k)
    {
        int lk=nxt(l,0),rk=nxt(r,1);
        //cout<<"adl:"<<l<<" adr:"<<r<<" adk:"<<k<<endl;
        splay(lk,0),splay(rk,lk),mark(son[rk][0],k);
    }
    int spaly(int u,int f)
    {
        int res;
        res=dep[u],dep[u]=1,add(f?-inf+1:key[fakefa[u]],f?key[fakefa[u]]:inf-1,1);
        fakeson[fakefa[u]][f]=fakeson[u][f^1],fakefa[fakeson[u][f^1]]=fakefa[u];
        fakefa[fakert]=u,fakeson[u][f^1]=fakert,fakert=u;
        return res;
    }
    int main()
    {
        rt=newnd(inf,0),son[rt][0]=newnd(-inf,rt);
        n=read();
        while(n--)
        {
            int f=read();
            if(f==1)
            {
                int k=read();ins(k);
                write(dep[cnt]);
            }
            else if(f==2)
            {
                int ans=0,u=nxt(-inf,1);
                if(fakert!=u)ans=spaly(u,0);
                else ans=1;
                write(ans);
            }
            else if(f==3)
            {
                int ans=0,u=nxt(inf,0);
                if(fakert!=u)ans=spaly(u,1);
                else ans=1;
                write(ans);
            }
            else if(f==4)
            {
                int ans=0,u=nxt(-inf,1);
                if(fakert!=u)ans=spaly(u,0);
                else ans=1;
                write(ans);
                fakert=fakeson[u][1],fakefa[fakert]=0,del(key[u]),add(-inf+1,inf-1,-1);
            }
            else if(f==5)
            {
                int ans=0,u=nxt(inf,0);
                if(fakert!=u)ans=spaly(u,1);
                else ans=1;
                write(ans);
                fakert=fakeson[u][0],fakefa[fakert]=0,del(key[u]),add(-inf+1,inf-1,-1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    手写排序
    cookie与session的区别
    索引有几种
    mysql优化怎么做?
    laravel Builder scope count() 出错 Eloquent/Builder.php 1185行
    鹏业软件喷淋的喷头改为上喷
    鹏业安装算量复制工程量
    鹏业软件安装算量计算规则,喷淋识别、以及保温设置的问题解决
    鹏业安装算量喷淋管件修改问题解答
    鹏业软件CAD云服务转图纸没反应的说明
  • 原文地址:https://www.cnblogs.com/xzyf/p/10275536.html
Copyright © 2011-2022 走看看