HNOI2017单旋

原题链接

我的方法是用另外一颗splay(以原来输入的关键码作为关键字)维护原树节点深度信息,使得在操作时能在原树上快速定位与查询。

为了方便,以下提到的splay都是维护信息的那颗splay,而不是用来模拟原来操作的那棵树。

对于插入,直接在splay中insert,再看它的前驱与后继谁的左/右儿子是空的,记录dep=dep[..]+1

对于单旋最小值m,发现在原树中m的右子树的深度不变,m深度变为1,其他点深度+1。记m在原树中的父亲为f,可以在splay中把f的前驱旋转到根,再把根的右子树打上+1的标记。单旋最小值m后删除m的话,发现在原树中m的右子树的深度-1,其他点深度不变,就对应的在splay中把f旋转到根,f的左子树打上-1,然后删除m即可。

最大值同理。

复杂度O(nlogn)

#include
#include
#include
#include
#include
#include
#define R return 0
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=150050;
void read(int &re)
{
    char ch=getchar();int g=1;
    while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
    re=0;
    while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48,ch=getchar();
    re*=g;
}
struct node
{
    int fa,ch[2];
}tr[N];

int dep[N],ch[N][2],fa[N],siz[N],dfn[N],sz=0,root=0,cnt=0,key[N];
int add[N],rt=0;
inline bool ge(int x) {return ch[fa[x]][1]==x;}
void up(int x)
{
    siz[x]=1;
    if(ch[x][0]) siz[x]+=siz[ch[x][0]];
    if(ch[x][1]) siz[x]+=siz[ch[x][1]];
}
void pushdown(int x)
{
    if(x&&add[x])
    {
        dep[x]+=add[x];
        if(ch[x][0]) add[ch[x][0]]+=add[x];
        if(ch[x][1]) add[ch[x][1]]+=add[x];
        add[x]=0;
    }
}
void rotate(int x)
{
    pushdown(fa[x]);pushdown(x);
    int f=fa[x],g=fa[f],wh=ge(x);
    ch[f][wh]=ch[x][wh^1]; fa[ch[f][wh]]=f;
    ch[x][wh^1]=f; fa[f]=x;
    fa[x]=g;
    if(g) ch[g][ch[g][1]==f]=x;
    up(f),up(x);
}
void splay(int x,int goal)
{
    if(!x) return ;
    for(int f;(f=fa[x])!=goal;rotate(x)) if(fa[f]!=goal) 
    rotate(ge(x)==ge(f)?f:x);
    if(!goal) root=x;
}
void clear(int x)
{
    ch[x][0]=ch[x][1]=fa[x]=dep[x]=siz[x]=dfn[x]=add[x]=key[x]=0;
    tr[x].ch[0]=tr[x].ch[1]=tr[x].fa=0;
}
int pre()
{
    int now=root;pushdown(now);
    if(!ch[now][0]) return 0;
    now=ch[now][0]; pushdown(now);
    while(ch[now][1]) now=ch[now][1],pushdown(now);
    return now;
}
int nex()
{
    int now=root;pushdown(now);
    if(!ch[now][1]) return 0;
    now=ch[now][1]; pushdown(now);
    while(ch[now][0]) now=ch[now][0],pushdown(now);
    return now;
}

int insert(int k)
{
    if(!root)
    {
        sz++;root=sz;dep[sz]=1;siz[sz]=1;dfn[sz]=++cnt;key[sz]=k;
        rt=sz;dep[sz]=1;
        return sz;
    }
    int now=root,f=0;
    while(1)
    {
        pushdown(now);
        int wh=key[now]<k;
        f=now;
        now=ch[now][wh];
        if(!now)
        {
            now=++sz;
            ch[f][wh]=now;fa[now]=f;key[now]=k;siz[now]=1;
            dfn[now]=++cnt;up(f);splay(now,0);
            return now;
        }
    }
}
int findmin()
{
    int now=root;pushdown(now);
    while(ch[now][0]) now=ch[now][0],pushdown(now);
    return now;
}
int findmax()
{
    int now=root;pushdown(now);
    while(ch[now][1]) now=ch[now][1],pushdown(now);
    return now;
}
//debug
void allpushdown(int x)
{
    pushdown(x);
    if(ch[x][0]) allpushdown(ch[x][0]);
    if(ch[x][1]) allpushdown(ch[x][1]);
}

int main()
{
    int i,j,x,y,T,k;
    read(T);
    for(i=1;i<=T;++i)
    {
        read(y);
        clear(0);
        if(y==1)
        {
            read(x);
            k=insert(x);
            if(siz[k]==1)
            {
                printf("1\n");
                continue;
            }
            int p=pre(),n=nex();
            if(!p||!n)
            {
                p=p+n;
                if(key[p]1]=k;
                else tr[p].ch[0]=k;
                tr[k].fa=p;
                dep[k]=dep[p]+1;
                printf("%d\n",dep[k]);
                continue;
            }
            
            clear(0);
            if(tr[p].ch[1]) tr[n].ch[0]=k,tr[k].fa=n,dep[k]=dep[n]+1;
            else if(tr[n].ch[0]) tr[p].ch[1]=k,tr[k].fa=p,dep[k]=dep[p]+1;
            printf("%d\n",dep[k]); //insert min!
        }
        else if(y==2)
        {
            x=findmin();
            pushdown(x);
            printf("%d\n",dep[x]);
            dep[x]=1;
            
            if(x==rt) continue;
            int f=tr[x].fa,now=x;
            tr[x].fa=0;tr[tr[x].ch[1]].fa=f;
            tr[f].ch[0]=tr[x].ch[1];tr[x].ch[1]=rt;
            tr[rt].fa=x;rt=x;
            
            clear(0);
            splay(f,0);
            now=pre();
            splay(now,0);
            if(ch[now][1]) add[ch[now][1]]++;
        }
        else if(y==3)
        {
            x=findmax();
            pushdown(x);
            printf("%d\n",dep[x]);
            dep[x]=1;
            if(x==rt) continue;
            
            int f=tr[x].fa,now=x;
            tr[x].fa=0;tr[tr[x].ch[0]].fa=f;
            tr[f].ch[1]=tr[x].ch[0];tr[x].ch[0]=rt;
            tr[rt].fa=x;rt=x;
            
            clear(0);
            splay(f,0);
            now=nex();
            splay(now,0);
            if(ch[now][0]) add[ch[now][0]]++;
        }
        else if(y==4)
        {//!!!!!!!!!!!!!!!
            x=findmin();
            pushdown(x);
            printf("%d\n",dep[x]);
            int f=tr[x].fa;
            if(x==rt) rt=tr[x].ch[1];
            tr[tr[x].ch[1]].fa=f;tr[f].ch[0]=tr[x].ch[1];
            tr[x].ch[1]=tr[x].ch[0]=tr[x].fa=0;
            clear(0);
            
            splay(x,0);
            root=ch[x][1];fa[root]=0;clear(x);
            if(f)
            {
                splay(f,0);
                if(ch[f][0]) add[ch[f][0]]--;
            }
            else 
            {
                if(root) add[root]--;
                else clear(rt),rt=0;
            }
        }
        else if(y==5)
        {
            x=findmax();
            pushdown(x);
            printf("%d\n",dep[x]);
            int f=tr[x].fa;
            if(x==rt) rt=tr[x].ch[0];
            tr[tr[x].ch[0]].fa=f;tr[f].ch[1]=tr[x].ch[0];
            tr[x].ch[1]=tr[x].ch[0]=tr[x].fa=0;
            clear(0);
            
            splay(x,0);
            root=ch[x][0];fa[root]=0;clear(x);
            if(f)
            {
                splay(f,0);
                if(ch[f][1]) add[ch[f][1]]--;
            }
            else 
            {
                if(root) add[root]--;
                else clear(rt),rt=0;
            }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/thkkk/p/7649515.html

你可能感兴趣的:(HNOI2017单旋)