zoukankan      html  css  js  c++  java
  • 序列操作(bzoj 1858)

    Description

    lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

    Input

    输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目 第二行包括n个数,表示序列的初始状态 接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作="" <="" div="">

    Output

    对于每一个询问操作,输出一行,包括1个数,表示其对应的答案

    Sample Input

    10 10
    0 0 0 1 1 0 1 0 1 1
    1 0 2
    3 0 5
    2 2 2
    4 0 4
    0 3 6
    2 3 7
    4 2 8
    1 0 5
    0 5 6
    3 3 9

    Sample Output

    5
    2
    6
    5

    HINT

    对于30%的数据,1<=n, m<=1000
    对于100%的数据,1<=n, m<=100000

    /*
        不想写线段树,写的分块。
        维护一下每个块的左最大连续区间,右最大连续区间,最大连续区间,和几个标记(无/全0/全1/取反)。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define N 100010
    #define M 510
    using namespace std;
    int a[N],bl[N],n,m,size;
    int tag[M],lc0[M],rc0[M],sc0[M],lc1[M],rc1[M],sc1[M],sum[M];
    
    void init(int i){
        tag[i]=-1;lc0[i]=rc0[i]=sc0[i]=lc1[i]=rc1[i]=sc1[i]=sum[i]=0;
        for(int j=(i-1)*size+1;j<=min(n,i*size);j++)
            if(a[j]) sum[i]++;
        int fl=0,p=0;
        for(int j=(i-1)*size+1;j<=min(n,i*size);j++){
            if(!a[j]&&!fl) lc0[i]++;
            else fl=1;
            if(!a[j]) p++;else p=0;
            sc0[i]=max(sc0[i],p);
        }
        fl=0;
        for(int j=min(n,i*size);j>(i-1)*size;j--){
            if(!a[j]&&!fl) rc0[i]++;
            else fl=1;
        }
        fl=0,p=0;
        for(int j=(i-1)*size+1;j<=min(n,i*size);j++){
            if(a[j]&&!fl) lc1[i]++;
            else fl=1;
            if(a[j]) p++;else p=0;
            sc1[i]=max(sc1[i],p);
        }
        fl=0;
        for(int j=min(n,i*size);j>(i-1)*size;j--){
            if(a[j]&&!fl) rc1[i]++;
            else fl=1;
        }
    }
    
    void pushdown(int i){
        if(tag[i]==-1) return;
        if(tag[i]==0||tag[i]==1)
            for(int j=(i-1)*size+1;j<=i*size;j++)
                a[j]=tag[i];
        else
            for(int j=(i-1)*size+1;j<=i*size;j++)
                a[j]^=1;
        tag[i]=-1;
    }
    
    void change1(int x,int y,int v){
        pushdown(bl[x]);
        for(int i=x;i<=min(y,bl[x]*size);i++) a[i]=v;
        init(bl[x]);
        for(int i=bl[x]+1;i<bl[y];i++){
            tag[i]=v;
            if(v) lc1[i]=rc1[i]=sc1[i]=sum[i]=size,lc0[i]=rc0[i]=sc0[i]=0;
            else lc1[i]=rc1[i]=sc1[i]=sum[i]=0,lc0[i]=rc0[i]=sc0[i]=size;
        }
        if(bl[x]==bl[y]) return;
        pushdown(bl[y]);
        for(int i=(bl[y]-1)*size+1;i<=y;i++) a[i]=v;
        init(bl[y]);
    }
    
    void change2(int x,int y){
        pushdown(bl[x]);
        for(int i=x;i<=min(y,bl[x]*size);i++) a[i]^=1;
        init(bl[x]);
        for(int i=bl[x]+1;i<bl[y];i++){
            if(tag[i]==-1) tag[i]=2;
            else if(tag[i]==0) tag[i]=1;
            else if(tag[i]==1) tag[i]=0;
            else tag[i]=-1;
            swap(lc0[i],lc1[i]);swap(rc0[i],rc1[i]);
            swap(sc0[i],sc1[i]);sum[i]=size-sum[i];
        }
        if(bl[x]==bl[y]) return;
        pushdown(bl[y]);
        for(int i=(bl[y]-1)*size+1;i<=y;i++) a[i]^=1;
        init(bl[y]);
    }
    
    int query1(int x,int y){
        int ans=0;
        pushdown(bl[x]);
        for(int i=x;i<=min(y,bl[x]*size);i++)
            if(a[i]) ans++;
        for(int i=bl[x]+1;i<bl[y];i++) ans+=sum[i];
        if(bl[x]==bl[y]) return ans;
        pushdown(bl[y]);
        for(int i=(bl[y]-1)*size+1;i<=y;i++)
            if(a[i]) ans++;
        return ans;
    }
    
    int query2(int x,int y){
        int ans=0,l=0;
        pushdown(bl[x]);
        for(int i=x;i<=min(y,bl[x]*size);i++){
            if(a[i]) l++;else l=0;
            ans=max(ans,l);
        }
        for(int i=bl[x]+1;i<bl[y];i++){
            l+=lc1[i];
            ans=max(ans,l);
            ans=max(ans,sc1[i]);
            if(lc1[i]!=size) l=rc1[i];
        }
        if(bl[x]==bl[y]) return max(ans,l);
        pushdown(bl[y]);
        for(int i=(bl[y]-1)*size+1;i<=y;i++){
            if(a[i]) l++;else l=0;
            ans=max(ans,l);
        }
        return ans;
    }
    
    int main(){
        memset(tag,-1,sizeof(tag));
        scanf("%d%d",&n,&m);size=sqrt(n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            bl[i]=(i-1)/size+1;
        }
        for(int i=1;i<=bl[n];i++) init(i);
        int op,x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&op,&x,&y);x++;y++;
            if(op==0) change1(x,y,0);
            if(op==1) change1(x,y,1);
            if(op==2) change2(x,y);
            if(op==3) printf("%d
    ",query1(x,y));
            if(op==4) printf("%d
    ",query2(x,y));
        }
        return 0;
    }
  • 相关阅读:
    拿webshell方法汇总
    Linux跑脚本用sh和./有什么区别?
    安全测试工具
    浏览器被劫持网上优秀的修复方法
    Linux 逻辑卷扩容
    sed替换文本
    mysql 用户创建,授权
    编程之约定
    java 对象成员变量初始化顺序
    java 静态成员初始化顺序
  • 原文地址:https://www.cnblogs.com/harden/p/6648548.html
Copyright © 2011-2022 走看看