zoukankan      html  css  js  c++  java
  • Hdu-3487 Splay树,删除,添加,Lazy延迟标记操作

     HDU_3487

    题意:给出n和q,n代表1-n的序列,接下来q有两种操作,Cut a b c:表示把区间[a,b]截掉然后放在第c个数的后面,Flip a b 表示把区间[a,b]反转,经过一系列的q操作,最后输出操作后的序列:

    分析:首先建立初始化的树结构之前,先给n设置个极限范围0和n+1,防止特殊情况下越界,如果反转[a,b],则先把第a-1个数放在根节点,把b+1结点的数放在根节点的右儿子下面,此时根节点的右儿子的左儿子为根的子树就是[a,b]区间,然后把反转标记传递给该子树的根节点,如果剪切区间[a,b]则把第c+1个数旋转到根节点处,然后把根节点的右儿子为子树的最左面的节点旋转到该子树的根,此时把剪掉的子树的根节点连到根节点的右儿子的左儿子上面即可,需要注意的是,push_down和push_up的操作

    codes:指针

    #include"stdio.h"
    #include"iostream"
    #include"queue"
    using namespace std;
    struct Link_cut
    {
    
        queue<int>q;
        struct node     //节点结构体
        {
            int key,val,son,flag;
            node *lson,*rson,*fa;  //左儿子,右儿子,以及父节点
            node()
            {
                key=val=flag=0;
                son=1;
                lson=rson=fa=NULL;
            }
        };
        node *top,*root,*x,*y;
        void init() //建立根节点root的父节点top
        {
            top=new node();
        }
        int getNum(node *x) //以x为根的子树一共有多少个节点
        {
            if(x==NULL)return 0;
            return x->son;
        }
        void push_up(node *rt)
        {
            rt->son=getNum(rt->lson)+getNum(rt->rson)+1;
        }
        void push_down(node *rt)
        {
            if(rt==NULL)return;
            if(rt->flag)
            {
                rt->flag^=1;
                Reversal(rt);
                if(rt->lson!=NULL)
                rt->lson->flag^=1;
                if(rt->rson!=NULL)
                rt->rson->flag^=1;
            }
        }
        void Rotate(node *x,int k)  //k=0左旋k=1右旋
        {
            node *y=x->fa;
            if(k==0)
            {
                y->rson=x->lson;
                if(y->rson!=NULL)
                    y->rson->fa=y;
    
                push_up(y);
                if(y->fa->rson==y)
                    y->fa->rson=x;
                else
                    y->fa->lson=x;
                x->fa=y->fa;
    
                x->lson=y;
                y->fa=x;
            }
            else
            {
                y->lson=x->rson;
                if(y->lson!=NULL)
                    y->lson->fa=y;
    
                push_up(y);
                if(y->fa->lson==y)
                    y->fa->lson=x;
                else
                    y->fa->rson=x;
                x->fa=y->fa;
    
                x->rson=y;
                y->fa=x;
            }
        }
        void Splay(node *x,node *f)//把x旋转到f的下面
        {
            while(x->fa!=f)
            {
                node *y=x->fa;
                node *z=y->fa;
                if(z==f)
                {
                    if(y->rson==x)
                        Rotate(x,0);
                    else
                        Rotate(x,1);
                }
                else
                {
                    if(z->rson==y)
                    {
                        if(y->rson==x)
                        {
                            Rotate(y,0);
                            Rotate(x,0);
                        }
                        else
                        {
                            Rotate(x,1);
                            Rotate(x,0);
                        }
                    }
                    else
                    {
                        if(y->lson==x)
                        {
                            Rotate(y,1);
                            Rotate(x,1);
                        }
                        else
                        {
                            Rotate(x,0);
                            Rotate(x,1);
                        }
                    }
                }
            }
            if(f==top)
                root=x;
        }
        void RotateTo(node *x,node *f)
        {
            Splay(x,f);
            push_up(x);
        }
        void RotateTo(int k,node *f)
        {
            node *x=root;
            k++;
            while(1)
            {
                push_down(x);
                int temp=getNum(x->lson)+1;
                if(k==temp)break;
                if(k<temp)
                    x=x->lson;
                else
                {
                    k-=temp;
                    x=x->rson;
                }
            }
            Splay(x,f);
            push_up(x);
        }
        void creatTree(int l,int r,int k,node *f) //初始化一颗二叉树
        {
            if(l>r)return;
            int mid=(l+r)/2;
            node *rt=new node();
            if(f==top)
                root=rt;
            if(k==0)
            {
                f->lson=rt;
                rt->fa=f;
                rt->key=mid;
            }
            else
            {
                f->rson=rt;
                rt->fa=f;
                rt->key=mid;
            }
            creatTree(l,mid-1,0,rt);
            creatTree(mid+1,r,1,rt);
            push_up(rt);
        }
        void Reversal(node *x)//交换x左右儿子的结点
        {
            if(x==NULL)return;
            node *y=x->lson;
            x->lson=x->rson;
            x->rson=y;
        }
        node *Find(int k) //找到第k的结点
        {
            node *x=root;
            k++;
            while(1)
            {
                push_down(x);
                int temp=getNum(x->lson)+1;
                if(k==temp)break;
                else if(k<temp)
                    x=x->lson;
                else
                {
                    k-=temp;
                    x=x->rson;
                }
            }
            return x;
        }
        node *FindRight(node *rt) //找到以rt为根节点的最右一个结点
        {
            node *x=rt;
            while(1)
            {
                push_down(x);
                if(x->rson==NULL)
                    break;
                x=x->rson;
            }
            return x;
        }
        node *FindLeft(node *rt)  //找到以rt为根节点的最左一个结点
        {
            node *x=rt;
            while(1)
            {
                push_down(x);
                if(x->lson==NULL)break;
                x=x->lson;
            }
            return x;
        }
        void Link(node *rt,int k) //把rt为根的子树连接到第k个结点的后面
        {
            root->rson->lson=NULL; //把区间砍掉
            node *x=Find(k);
            RotateTo(x,top);
            node *y=FindLeft(root->rson);
            RotateTo(y,root);
    
            root->rson->lson=rt;
            rt->fa=root->rson;
        }
        void Output(node *x,int n)
        {
            if(x==NULL)return;
            push_down(x);
            Output(x->lson,n);
            if(x->key>=1&&x->key<=n)
            q.push(x->key);
            Output(x->rson,n);
        }
    }h;
    int main()
    {
        int n,q;
        while(scanf("%d%d",&n,&q)!=-1)
        {
            if(n==-1&&q==-1)break;
            h.init();
            h.creatTree(0,n+1,0,h.top);
            char op[11];
            int a,b,c;
    
            while(q--)
            {
    
                scanf("%s%d%d",op,&a,&b);
                if(op[0]=='C')
                {
                    scanf("%d",&c);
                    h.RotateTo(a-1,h.top);
                    h.RotateTo(b+1,h.root);
                    h.Link(h.root->rson->lson,c);
                }
                else
                {
                    h.RotateTo(a-1,h.top);
                    h.RotateTo(b+1,h.root);
                    h.root->rson->lson->flag^=1;
                }
            }
            while(!h.q.empty())
            {
                h.q.pop();
            }
            h.Output(h.root,n);
            printf("%d",h.q.front());
            h.q.pop();
            while(!h.q.empty())
            {
                printf(" %d",h.q.front());
                h.q.pop();
            }
            puts("");
    
        }
    }
    /*
    8 1
    CUT 3 5 4
    
    5 1
    CUT 2 3 1
    
    8 3
    Cut 3 6 3
    Cut 2 6 2
    Cut 3 6 4
    
    8 1
    Flip 2 6
    
    10 5
    Cut 2 6 3
    Flip 4 9
    Flip 5 8
    Cut 6 7 3
    Flip 4 5
    */
    View Code

    codes:数组模拟

    #include"stdio.h"
    #include"iostream"
    #include"queue"
    #include"string.h"
    #define M 3000005
    using namespace std;
    
    struct Text
    {
        int son[M][2],fa[M],flip[M],num[M];
        int top;
        int root;
        vector<int>p;
        void init(int n)
        {
            top=n+2;
            for(int i=0;i<=n+2;i++)
            {
                num[i]=1;
                flip[i]=0;
                son[i][0]=son[i][1]=-1;
                fa[i]=-1;
            }
        }
        void Rotate(int x,int k)
        {
            int y=fa[x];
            if(k==0)
            {
                son[y][1]=son[x][0];
                if(son[y][1]!=-1)
                    fa[son[y][1]]=y;
    
                push_up(y);
                if(son[fa[y]][0]==y)
                    son[fa[y]][0]=x;
                else
                    son[fa[y]][1]=x;
                fa[x]=fa[y];
    
                son[x][0]=y;
                fa[y]=x;
            }
           else
            {
                son[y][0]=son[x][1];
                if(son[y][0]!=-1)
                    fa[son[y][0]]=y;
    
                push_up(y);
                if(son[fa[y]][0]==y)
                    son[fa[y]][0]=x;
                else
                    son[fa[y]][1]=x;
                fa[x]=fa[y];
    
                son[x][1]=y;
                fa[y]=x;
            }
        }
        int Find(int k)
        {
            k++;
            int x=root;
            while(1)
            {
                push_down(x);
                int temp=getNum(son[x][0])+1;
                if(temp==k)break;
                else if(k<temp)
                    x=son[x][0];
                else
                {
                    k-=temp;
                    x=son[x][1];
                }
            }
            return x;
        }
        void splay(int x,int f)
        {
            if(x==-1)return;
            while(fa[x]!=f)
            {
                int y=fa[x];
                int z=fa[y];
                if(z==f)
                {
                    if(son[y][0]==x)
                        Rotate(x,1);
                    else
                        Rotate(x,0);
                }
                else
                {
                    if(son[z][0]==y)
                    {
                        if(son[y][0]==x)
                        {
                            Rotate(y,1);
                            Rotate(x,1);
                        }
                        else
                        {
                            Rotate(x,0);
                            Rotate(x,1);
                        }
                    }
                    else
                    {
                        if(son[y][1]==x)
                        {
                            Rotate(y,0);
                            Rotate(x,0);
                        }
                        else
                        {
                            Rotate(x,1);
                            Rotate(x,0);
                        }
                    }
                }
            }
            if(f==top)
                root=x;
        }
        void RotateTo(int x,int f,int type)
        {
            if(!type)
                x=Find(x);
            splay(x,f);
            push_up(x);
        }
        void Reversal(int x)
        {
            if(x==-1)return;
            int y=son[x][0];
            son[x][0]=son[x][1];
            son[x][1]=y;
        }
        void creat(int l,int r,int k,int f)
        {
            if(l>r)return;
            int mid=(l+r)/2;
            if(f==top)
                root=mid;
            son[f][k]=mid;
            fa[mid]=f;
            creat(l,mid-1,0,mid);
            creat(mid+1,r,1,mid);
            push_up(mid);
        }
        int getNum(int x)
        {
            if(x==-1)return 0;
            return num[x];
        }
        void push_up(int rt)
        {
            num[rt]=getNum(son[rt][0])+getNum(son[rt][1])+1;
        }
        void push_down(int rt)
        {
            if(rt==-1)return;
            if(flip[rt])
            {
                flip[rt]^=1;
                Reversal(rt);
                if(son[rt][0]!=-1)
                    flip[son[rt][0]]^=1;
                if(son[rt][1]!=-1)
                    flip[son[rt][1]]^=1;
            }
        }
        int findLeft(int rt)
        {
            int x=rt;
            while(1)
            {
                push_down(x);
                if(son[x][0]==-1)break;
                x=son[x][0];
            }
            return x;
        }
        void CUT(int a,int b,int c)
        {
            RotateTo(a-1,top,0);
            RotateTo(b+1,root,0);
            int rt=son[son[root][1]][0];
            son[son[root][1]][0]=-1;
    
            RotateTo(c,top,0);
            int x=findLeft(son[root][1]);
            RotateTo(x,root,1);
            son[son[root][1]][0]=rt;
            fa[rt]=son[root][1];
        }
        void FLIP(int a,int b)
        {
            RotateTo(a-1,top,0);
            RotateTo(b+1,root,0);
            int x=son[son[root][1]][0];
            flip[x]^=1;
        }
        void dfs(int rt,int n)
        {
            if(rt==-1)return;
            push_down(rt);
            dfs(son[rt][0],n);
            if(rt>=1&&rt<=n)
                p.push_back(rt);
            dfs(son[rt][1],n);
    
        }
        void Output(int n)
        {
            dfs(root,n);
            printf("%d",p[0]);
            for(int i=1;i<(int)p.size();i++)
                printf(" %d",p[i]);
            puts("");
            p.clear();
        }
    }text;
    int main()
    {
        int n,q;
        while(scanf("%d%d",&n,&q)!=-1)
        {
            if(n==q&&n==-1)break;
            text.init(n);
            text.creat(0,n+1,0,text.top);
            int a,b,c;
            char op[10];
    
            while(q--)
            {
                scanf("%s%d%d",op,&a,&b);
                if(op[0]=='C')
                {
                    scanf("%d",&c);
                    text.CUT(a,b,c);
                }
                else
                    text.FLIP(a,b);
    
    
            }
            text.Output(n);
    
        }
        return 0;
    }
    
    
    /*
    10 5
    Cut 2 6 3
    Flip 4 9
    Flip 5 8
    Cut 6 7 3
    Flip 4 5
    
    
    10 5
    Flip 4 9
    Flip 5 8
    Cut 6 7 3
    Flip 4 5
    
    10 1
    Flip 2 9
    */
    View Code
     
  • 相关阅读:
    C#实现程序的版本升级更新
    c#获取系统内存等信息
    C# 时间格式设置
    SMS(System Management Server)学习笔记。
    C#调用WMI获取本机MAC地址列表。
    sharepoint portal service 一处隐蔽应用。
    ubuntu安装显卡驱动后亮度不能调节问题
    linux下boost编译及链接到系统目录
    在windows下修改右键菜单以实现使用vs2010快速编译代码
    vs2010使用boost::interpocess编译出错
  • 原文地址:https://www.cnblogs.com/mypsq/p/4826540.html
Copyright © 2011-2022 走看看