zoukankan      html  css  js  c++  java
  • BZOJ3223文艺平衡树——非旋转treap

    此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:

    翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

    输入

    第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
    接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n

    输出

    输出一行n个数字,表示原始序列经过m次变换后的结果

    样例输入

    5 3
    1 3
    1 3
    1 4

    样例输出

    4 3 2 1 5

    提示

    n,m<=100000

    非旋转treap相比于旋转treap支持区间操作,所以对于这道题只需要每次把树拆成[1~l-1]、[l~r]、[r+1~tot]三段,然后把[l~r]打上标记进行翻转,再把三段区间合并就行了。对于打标记的点只有在查到这个点时才翻转,如果一个点被打了两次标记就相当于不翻转。

    最后附上代码.

    指针版

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0,f=1; char c=nc(); while(!isdigit(c)) {if(c=='-') f=-1; c=nc();} while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
    ll rd2() {ll x=0,f=1; char c=nc(); while(!isdigit(c)) {if(c=='-') f=-1; c=nc();} while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
    int n,m;
    int L,R;
    struct treap
    {
        int size;
        int rnd;
        int val;
        int rev;
        treap *ls,*rs;
        treap(){}
        treap(int k,treap *son)
        {
            size=1;
            rnd=rand();
            val=k;
            ls=rs=son;
            rev=0;
        }
        void pushup()
        {
            size=ls->size+rs->size+1;
        }
        void pushdown()
        {
            if(rev)
            {
                rev^=1;
                ls->rev^=1;
                rs->rev^=1;
                swap(ls,rs);
            }
        }
    }tr[100010],nil;
    typedef treap* node;
    node root,cnt,null;
    void init()
    {
        nil=treap(0,NULL);
        null=&nil;
        null->ls=null->rs=null;
        null->size=0;
        root=null;
        cnt=tr;
    }
    node build(int x)
    {
        *cnt=treap(x,null);
        return cnt++;
    }
    node merge(node x,node y)
    {
        if(x==null)
        {
            return y; 
        }
        if(y==null)
        {
            return x;
        }
        x->pushdown();
        y->pushdown();
        if(x->rnd<y->rnd)
        {
            x->rs=merge(x->rs,y);
            x->pushup();
            return x;
        }
        else
        {
            y->ls=merge(x,y->ls);
            y->pushup();
            return y;
        }
    }
    void split(node rt,node &x,node &y,int k)
    {
        if(rt==null)
        {
            x=y=null;
            return ;
        }
        rt->pushdown();
        if(rt->ls->size>=k)
        {
            y=rt;
            split(rt->ls,x,y->ls,k);
            rt->pushup();
        }
        else
        {
            x=rt;
            split(rt->rs,x->rs,y,k-rt->ls->size-1);
            rt->pushup();
        }
    }
    void print(node rt)
    {
        rt->pushdown();
        if(rt->ls!=null)
        {
            print(rt->ls);
        }
        printf("%d",rt->val);
        if(--n!=0)
        {
            printf(" ");
        }
        if(rt->rs!=null)
        {
            print(rt->rs);
        }
    }
    node build_tree(int l,int r)
    {
        if(l==r)
        {
            return build(l);
        }
        int mid=(l+r)>>1;
        return merge(build_tree(l,mid),build_tree(mid+1,r));
    }
    int main()
    {
        init();
        n=rd();
        m=rd();
        root=build_tree(1,n);
        while(m--)
        {
            L=rd();
            R=rd();
            node x,y,z;
            split(root,y,z,R);
            split(y,x,y,L-1);
            y->rev^=1;
            root=merge(merge(x,y),z);
        }
        print(root);
    }
    

    非指针版

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    using namespace std;
    int n,m;
    int r[100010];
    int v[100010];
    int s[100010][3];
    int size[100010];
    bool d[100010];
    int root;
    int tot;
    int L,R;
    int x,y,z;
    int flag;
    void pushup(int x)
    {
        size[x]=size[s[x][0]]+size[s[x][1]]+1;
    }
    int build(int x)
    {
        v[++tot]=x;
        r[tot]=rand();
        size[tot]=1;
        return tot;
    }
    void pushdown(int x)
    {
        swap(s[x][0],s[x][1]);
        if(s[x][0])
        {
            d[s[x][0]]^=1;
        }
        if(s[x][1])
        {
            d[s[x][1]]^=1;
        }
        d[x]=0;
    }
    int merge(int x,int y)
    {
        if(!x||!y)
        {
            return x+y;
        }
        if(r[x]<r[y])
        {
            if(d[x])
            {
                pushdown(x);
            }
            s[x][1]=merge(s[x][1],y);
            pushup(x);
            return x;
        }
        else
        {
            if(d[y])
            {
                pushdown(y);
            }
            s[y][0]=merge(x,s[y][0]);
            pushup(y);
            return y;
        }
    }
    void split(int i,int k,int &x,int &y)
    {
        if(!i)
        {
            x=y=0;
            return ;
        }
        if(d[i])
        {
            pushdown(i);
        }
        if(size[s[i][0]]<k)
        {
            x=i;
            split(s[i][1],k-size[s[i][0]]-1,s[i][1],y);
        }
        else
        {
            y=i;
            split(s[i][0],k,x,s[i][0]);
        }
        pushup(i);
    }
    void print(int x)
    {
        if(!x)
        {
            return ;
        }
        if(d[x])
        {
            pushdown(x);
        }
        print(s[x][0]);
        if(flag==0)
        {
            printf("%d",v[x]);
            flag=1;
        }
        else
        {
            printf(" %d",v[x]);
        }
        print(s[x][1]);
    }
    int main()
    {
        srand(12378);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            root=merge(root,build(i));
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&L,&R);
            split(root,L-1,x,y);
            split(y,R-L+1,y,z);
            d[y]^=1;
            root=merge(merge(x,y),z);
        }
        print(root);
        return 0;
    }
  • 相关阅读:
    号称简明实用的django上手教程
    转先验概率、最大似然估计、贝叶斯估计、最大后验概率
    转基于概率的矩阵分解原理详解(PMF)
    转浅谈矩阵分解在推荐系统中的应用
    转推荐算法——基于矩阵分解的推荐算法
    代码生成器的需求
    兼容性的设计要求
    API设计的需求
    有关表单的需求梳理
    element-ui table 点击分页table滚到顶部
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9090646.html
Copyright © 2011-2022 走看看