• BZOJ1858: [Scoi2010]序列操作


    【传送门:BZOJ1858


    简要题意:

      给出一个长度为n的01序列,有五种操作,m个操作:

      0 x y将第x个数到第y个数都变成0

      1 x y将第x个数到第y个数都变成1

      2 x y将第x个数到第y个数的所有数取反(即0变为1,1变为0)

      3 x y求出第x个数到第y个数有多少个1

      4 x y求出第x个数到第y个数最多有多少个连续的1


    题解:

      线段树麻烦题

      对于一段区间,我们维护这些东西:

      c表示有多少个1,c0表示最多有多少个连续的0,c1表示最多有多少个连续的1

      lc0表示从左端点开始向右有多少个连续的0,lc1表示从左端点开始向右有多少个连续的1

      rc0表示从右端点开始向左有多少个连续的0,rc1表示从右端点开始向左有多少个连续的1

      然后对于标记,lazy01表示当前区间的子区间变0或变1或不变,fan表示当前区间是否需要取反

      因为不能知道先后顺序,所以我们使得这两个标记在一个区间内不同时存在就好了

      假如当前区间原本就有取反标记,如果我要使得这个区间变为0或1,那么就要把取反标记去掉(因为这个时候取反没有用的,反正也会变成0或1)

      假如当前区间原本就有01标记,如果我要使得这个区间取反,那么就要把取反标记去掉,然后把01标记变成另一个01标记(也就是原本要变0的就变1,原本要变1的就变0,就是相当于取反了)

      然后其他的无脑做就好了,第四个操作略微有些麻烦


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct node
    {
        int l,r,lc,rc,c,c0,c1;
        int lc0,lc1,rc0,rc1;
        int lazy01,fan;
    }tr[210000];int trlen;
    void bt(int l,int r)
    {
        int now=++trlen;
        tr[now].l=l;tr[now].r=r;
        tr[now].c=tr[now].c0=tr[now].c1=tr[now].lc0=tr[now].lc1=tr[now].rc0=tr[now].rc1=0;
        tr[now].lazy01=-1;tr[now].fan=0;
        tr[now].lc=tr[now].rc=-1;
        if(l<r)
        {
            int mid=(l+r)/2;
            tr[now].lc=trlen+1;bt(l,mid);
            tr[now].rc=trlen+1;bt(mid+1,r);
        }
    }
    void follow(int now)
    {
        int lc=tr[now].lc,rc=tr[now].rc;
        
        tr[now].c=tr[lc].c+tr[rc].c;
        
        tr[now].c0=max(tr[lc].rc0+tr[rc].lc0,max(tr[lc].c0,tr[rc].c0));
        tr[now].c1=max(tr[lc].rc1+tr[rc].lc1,max(tr[lc].c1,tr[rc].c1));
        
        if(tr[lc].lc0==(tr[lc].r-tr[lc].l+1)&&tr[rc].rc0==(tr[rc].r-tr[rc].l+1)) tr[now].lc0=tr[now].rc0=tr[now].r-tr[now].l+1;
        else if(tr[lc].lc0==(tr[lc].r-tr[lc].l+1)&&tr[rc].rc0!=(tr[rc].r-tr[rc].l+1)) tr[now].lc0=tr[lc].lc0+tr[rc].lc0,tr[now].rc0=tr[rc].rc0;
        else if(tr[lc].lc0!=(tr[lc].r-tr[lc].l+1)&&tr[rc].rc0==(tr[rc].r-tr[rc].l+1)) tr[now].rc0=tr[lc].rc0+tr[rc].rc0,tr[now].lc0=tr[lc].lc0;
        else tr[now].lc0=tr[lc].lc0,tr[now].rc0=tr[rc].rc0;
        
        if(tr[lc].lc1==(tr[lc].r-tr[lc].l+1)&&tr[rc].rc1==(tr[rc].r-tr[rc].l+1)) tr[now].lc1=tr[now].rc1=tr[now].r-tr[now].l+1;
        else if(tr[lc].lc1==(tr[lc].r-tr[lc].l+1)&&tr[rc].rc1!=(tr[rc].r-tr[rc].l+1)) tr[now].lc1=tr[lc].lc1+tr[rc].lc1,tr[now].rc1=tr[rc].rc1;
        else if(tr[lc].lc1!=(tr[lc].r-tr[lc].l+1)&&tr[rc].rc1==(tr[rc].r-tr[rc].l+1)) tr[now].rc1=tr[lc].rc1+tr[rc].rc1,tr[now].lc1=tr[lc].lc1;
        else tr[now].lc1=tr[lc].lc1,tr[now].rc1=tr[rc].rc1;
    }
    void update01(int now)
    {
        int lc=tr[now].lc,rc=tr[now].rc;
        if(lc!=-1)
        {
            if(tr[now].lazy01==0)
            {
                tr[lc].c=tr[lc].c1=0;
                tr[lc].c0=tr[lc].r-tr[lc].l+1;
                tr[lc].lc0=tr[lc].rc0=tr[lc].r-tr[lc].l+1;
                tr[lc].lc1=tr[lc].rc1=0;
                tr[lc].lazy01=0;
            }
            else
            {
                tr[lc].c=tr[lc].c1=tr[lc].r-tr[lc].l+1;
                tr[lc].c0=0;
                tr[lc].lc0=tr[lc].rc0=0;
                tr[lc].lc1=tr[lc].rc1=tr[lc].r-tr[lc].l+1;
                tr[lc].lazy01=1;
            }
            if(tr[lc].fan==1) tr[lc].fan=0;
        }
        if(rc!=-1)
        {
            if(tr[now].lazy01==0)
            {
                tr[rc].c=tr[rc].c1=0;
                tr[rc].c0=tr[rc].r-tr[rc].l+1;
                tr[rc].lc0=tr[rc].rc0=tr[rc].r-tr[rc].l+1;
                tr[rc].lc1=tr[rc].rc1=0;
                tr[rc].lazy01=0;
            }
            else
            {
                tr[rc].c=tr[rc].c1=tr[rc].r-tr[rc].l+1;
                tr[rc].c0=0;
                tr[rc].lc0=tr[rc].rc0=0;
                tr[rc].lc1=tr[rc].rc1=tr[rc].r-tr[rc].l+1;
                tr[rc].lazy01=1;
            }
            if(tr[rc].fan==1) tr[rc].fan=0;
        }
        tr[now].lazy01=-1;
    }
    void updatef(int now)
    {
        int lc=tr[now].lc,rc=tr[now].rc;
        if(lc!=-1)
        {
            tr[lc].c=(tr[lc].r-tr[lc].l+1)-tr[lc].c;
            swap(tr[lc].c0,tr[lc].c1);
            swap(tr[lc].lc0,tr[lc].lc1);
            swap(tr[lc].rc0,tr[lc].rc1);
            tr[lc].fan^=1;
            if(tr[lc].fan==1&&tr[lc].lazy01!=-1)
            {
                tr[lc].lazy01^=1;
                tr[lc].fan=0;
            }
        }
        if(rc!=-1)
        {
            tr[rc].c=(tr[rc].r-tr[rc].l+1)-tr[rc].c;
            swap(tr[rc].c0,tr[rc].c1);
            swap(tr[rc].lc0,tr[rc].lc1);
            swap(tr[rc].rc0,tr[rc].rc1);
            tr[rc].fan^=1;
            if(tr[rc].fan==1&&tr[rc].lazy01!=-1)
            {
                tr[rc].lazy01^=1;
                tr[rc].fan=0;
            }
        }
        tr[now].fan=0;
    }
    void change(int now,int l,int r,int c)
    {
        if(tr[now].l==l&&tr[now].r==r)
        {
            if(c==0)
            {
                tr[now].c=tr[now].c1=0;
                tr[now].c0=r-l+1;
                tr[now].lc0=tr[now].rc0=r-l+1;
                tr[now].lc1=tr[now].rc1=0;
                tr[now].lazy01=0;
            }
            else
            {
                tr[now].c=tr[now].c1=r-l+1;
                tr[now].c0=0;
                tr[now].lc0=tr[now].rc0=0;
                tr[now].lc1=tr[now].rc1=r-l+1;
                tr[now].lazy01=1;
            }
            if(tr[now].fan==1) tr[now].fan=0;
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy01!=-1) update01(now);
        if(tr[now].fan==1) updatef(now);
        if(r<=mid) change(lc,l,r,c);
        else if(l>mid) change(rc,l,r,c);
        else change(lc,l,mid,c),change(rc,mid+1,r,c);
        follow(now);
    }
    void qufan(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r)
        {
            tr[now].c=(r-l+1)-tr[now].c;
            swap(tr[now].c0,tr[now].c1);
            swap(tr[now].lc0,tr[now].lc1);
            swap(tr[now].rc0,tr[now].rc1);
            tr[now].fan^=1;
            if(tr[now].fan==1&&tr[now].lazy01!=-1)
            {
                tr[now].lazy01^=1;
                tr[now].fan=0;
            }
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy01!=-1) update01(now);
        if(tr[now].fan==1) updatef(now);
        if(r<=mid) qufan(lc,l,r);
        else if(l>mid) qufan(rc,l,r);
        else qufan(lc,l,mid),qufan(rc,mid+1,r);
        follow(now);
    }
    int findc(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r) return tr[now].c;
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy01!=-1) update01(now);
        if(tr[now].fan==true) updatef(now);
        if(r<=mid) return findc(lc,l,r);
        else if(l>mid) return findc(rc,l,r);
        else return findc(lc,l,mid)+findc(rc,mid+1,r);
    }
    int tot,p[110000];
    void findd(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r)
        {
            p[++tot]=now;
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy01!=-1) update01(now);
        if(tr[now].fan==true) updatef(now);
        if(r<=mid) findd(lc,l,r);
        else if(l>mid) findd(rc,l,r);
        else findd(lc,l,mid),findd(rc,mid+1,r);
    }
    int a[110000];
    int main()
    {
        freopen("operation.in","r",stdin);
        freopen("operation.out","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        trlen=0;bt(1,n);
        for(int i=1;i<=n;i++)
        {
            int c;
            scanf("%d",&c);
            change(1,i,i,c);
        }
        for(int i=1;i<=m;i++)
        {
            int opt,x,y;
            scanf("%d%d%d",&opt,&x,&y);x++;y++;
            if(opt==0) change(1,x,y,0);
            if(opt==1) change(1,x,y,1);
            if(opt==2) qufan(1,x,y);
            if(opt==3) printf("%d
    ",findc(1,x,y));
            if(opt==4)
            {
                tot=0;
                findd(1,x,y);
                int ans=0,t=0;
                for(int i=1;i<=tot;i++)
                {
                    ans=max(ans,tr[p[i]].c1);
                    if(tr[p[i]].c1==(tr[p[i]].r-tr[p[i]].l+1)) t+=tr[p[i]].c1;
                    else
                    {
                        ans=max(ans,t+tr[p[i]].lc1);
                        t=tr[p[i]].rc1;
                    }
                    ans=max(ans,t);
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    vector详解
    笔记
    积木大赛
    codevs 1086 栈(Catalan数)
    不要把球传我
    同余方程 (codevs1200)
    最小集合
    数的计算
    产生数
    逃跑的拉尔夫
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8792942.html
Copyright © 2020-2023  润新知