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

 

 

 

转载于:https://www.cnblogs.com/mypsq/p/4826540.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值