• 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<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #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
    ");
                    continue;
                }
                int p=pre(),n=nex();
                if(!p||!n)
                {
                    p=p+n;
                    if(key[p]<x) tr[p].ch[1]=k;
                    else tr[p].ch[0]=k;
                    tr[k].fa=p;
                    dep[k]=dep[p]+1;
                    printf("%d
    ",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
    ",dep[k]); //insert min!
            }
            else if(y==2)
            {
                x=findmin();
                pushdown(x);
                printf("%d
    ",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
    ",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
    ",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
    ",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;
    }
  • 相关阅读:
    进程哪一个cpu
    AT&T 和 Intel 汇编语法的主要区别
    机器学习之一:线性回归、梯度下降算法
    解决Webstom 2017中,输入法候选框无法显示问题
    即时通信系统Openfire分析之八:集群管理
    即时通信系统Openfire分析之七:集群配置
    即时通信系统Openfire分析之六:路由表 RoutingTable
    即时通信系统Openfire分析之五:会话管理
    即时通信系统Openfire分析之四:消息路由
    即时通信系统Openfire分析之三:ConnectionManager 连接管理
  • 原文地址:https://www.cnblogs.com/thkkk/p/7649515.html
Copyright © 2020-2023  润新知