• HDU 3487 Play with Chain 【Splay】


    1-n的序列,有两种操作:

    1,将一段区间翻转

    2,将一段区间切下来放到剩余序列的第C个数后

    采用延迟更新的方法维护区间的翻转,并维护一个size域。

    添加一个最大点和一个最小点,防止出界

    翻转时,将第L-1个点伸展到跟,再将第R+1个点伸展到L-1的右子树,这时R+1的左子树就是要翻转的区间,加上一个标记。

    切区间时,跟翻转操作差不多,只是不加标记。然后找到C+1和C,将C伸展到根,C+1伸展到C的右子树,此时C+1的左子树就是要插入的位置。

    其实我说了这么多并没有什么卵用。。。。最后还是得自己画图看才能懂。

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    const int N=3e5+111;
    int data[N],num[N],t[N][2],id,fa[N];
    int flip[N],root,f;
    inline void pushup(int x){
        num[x]=num[t[x][0]]+num[t[x][1]]+1;
    }
    inline void pushdown(int x){
        if(flip[x]){
            flip[x]=0;
            flip[t[x][0]]^=1;
            flip[t[x][1]]^=1;
            swap(t[x][0],t[x][1]);
        }
    }
    inline void Rotate(int x,int w){
        int y=fa[x];
        int z=fa[y];
        pushdown(y);
        t[y][!w]=t[x][w];
        fa[t[x][w]]=y;
        t[z][t[z][1]==y]=x;
        fa[x]=z;
        t[x][w]=y;
        fa[y]=x;
        pushup(y);
    }
    void newnode(int &x,int y,int v){
        x=++id;
        t[x][0]=t[x][1]=0;
        fa[x]=y;
        data[x]=v,flip[x]=0;
        num[x]=1;
    }
    void build(int &x,int y,int l,int r){
        if(l<=r){
            int mid=(l+r)>>1;
            newnode(x,y,mid);
            build(t[x][0],x,l,mid-1);
            build(t[x][1],x,mid+1,r);
            pushup(x);
        }
    }
    void init(int n){
        f=id=root=0;
        t[0][0]=t[0][1]=num[0]=data[0]=flip[0]=fa[0]=0;
        newnode(root,0,-1);
        newnode(t[1][1],root,-1);
        build(t[t[1][1]][0],t[1][1],1,n);
        pushup(t[1][1]);
        pushup(1);
    }
    void Splay(int x,int y){
        if(x!=y){
            pushdown(x);
            while(fa[x]!=y){
                if(t[fa[x]][0]==x)
                    Rotate(x,1);
                else
                    Rotate(x,0);
            }
            pushup(x);
            if(!y)root=x;
        }
    }
    int Kth(int k){
        int x=root;
        pushdown(root);
        for(;num[t[x][0]]+1!=k;){
            if(num[t[x][0]]+1>k)
                x=t[x][0];
            else
                k-=num[t[x][0]]+1,x=t[x][1];
            pushdown(x);
        }
        return x;
    }
    void Flip(int a,int b){
        a=Kth(a);
        b=Kth(b+2);
        Splay(a,0);
        Splay(b,a);
        flip[t[b][0]]^=1;
    }
    void Cut(int a,int b,int c){
        int tmp,d;
        
        a=Kth(a);b=Kth(b+2);
        Splay(a,0);Splay(b,a);
        tmp=t[b][0];t[b][0]=0;
        pushup(b);pushup(a);
        
        d=Kth(c+2);c=Kth(c+1);
        Splay(c,0);Splay(d,c);
        t[d][0]=tmp;fa[tmp]=d;
        pushup(d);pushup(c);
    }
    void Inorder(int x){
        if(x){
            pushdown(x);
            Inorder(t[x][0]);
            if(data[x]>0){
                if(f)
                    putchar(' ');
                else    f=1;
                printf("%d",data[x]);
            }
            Inorder(t[x][1]);
        }
    }
    int main(){
        int n,m;
        char op[9];
        while(scanf("%d%d",&n,&m)!=EOF){
            if(n==-1)break;
            init(n);
            int a,b,c;
            while(m--){
                scanf("%s",op);
                if(op[0]=='F'){
                    scanf("%d%d",&a,&b);
                    Flip(a,b);
                }else{
                    scanf("%d%d%d",&a,&b,&c);
                    Cut(a,b,c);
                }
            }
            Inorder(root);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    java内部类与其他类变量之间的调用方式
    java线程数设置和系统cpu的关系
    IDEA设置方法自动显示参数提示
    (十)学生课程表查询
    (九)协处理器
    (八)filter的使用
    (七)多线程写入数据
    (六)mapreduce和Hbase集成
    (五)阅读推荐
    (四)region代码实现
  • 原文地址:https://www.cnblogs.com/L-King/p/5696907.html
Copyright © 2020-2023  润新知