• [SCOI2010]序列操作[分块or线段树]


    #include<cstdio>
    #include<iostream>
    #define lc k<<1
    #define rc k<<1|1
    using namespace std;
    const int N=1e5+5;
    int n,m,a[N];
    struct sgt{
        int sum,tag,rev,max1,max0,lss0,rss0,lss1,rss1,lp,rp,l,r;
    }s,tr[N<<2];
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    sgt merge(sgt left,sgt right){
        sgt now;
        now.lp=left.lp;
        now.rp=right.rp;
        now.sum=left.sum+right.sum;
        
        now.lss0=left.lss0;
        now.rss0=right.rss0;
        if(!right.lp&&!left.sum) now.lss0=max(now.lss0,left.r-left.l+1+right.lss0);
        if(!left.rp&&!right.sum) now.rss0=max(now.rss0,right.r-right.l+1+left.rss0);
        now.max0=max(left.max0,right.max0);
        if(!left.rp&&!right.lp) now.max0=max(now.max0,left.rss0+right.lss0);
    
        now.lss1=left.lss1;
        now.rss1=right.rss1;
        if(right.lp&&left.sum==left.r-left.l+1) now.lss1=max(now.lss1,left.sum+right.lss1);
        if(left.rp&&right.sum==right.r-right.l+1) now.rss1=max(now.rss1,right.sum+left.rss1);
        now.max1=max(left.max1,right.max1);
        if(left.rp&&right.lp) now.max1=max(now.max1,left.rss1+right.lss1);
        return now;
    }
    void updata(int k){
        tr[k].lp=tr[lc].lp;
        tr[k].rp=tr[rc].rp;
        tr[k].sum=tr[lc].sum+tr[rc].sum;
        
        tr[k].lss0=tr[lc].lss0;
        tr[k].rss0=tr[rc].rss0;
        if(!tr[rc].lp&&!tr[lc].sum) tr[k].lss0=max(tr[k].lss0,tr[lc].r-tr[lc].l+1+tr[rc].lss0);
        if(!tr[lc].rp&&!tr[rc].sum) tr[k].rss0=max(tr[k].rss0,tr[rc].r-tr[rc].l+1+tr[lc].rss0);
        tr[k].max0=max(tr[lc].max0,tr[rc].max0);
        if(!tr[lc].rp&&!tr[rc].lp) tr[k].max0=max(tr[k].max0,tr[lc].rss0+tr[rc].lss0);
    
        tr[k].lss1=tr[lc].lss1;
        tr[k].rss1=tr[rc].rss1;
        if(tr[rc].lp&&tr[lc].sum==tr[lc].r-tr[lc].l+1) tr[k].lss1=max(tr[k].lss1,tr[lc].sum+tr[rc].lss1);
        if(tr[lc].rp&&tr[rc].sum==tr[rc].r-tr[rc].l+1) tr[k].rss1=max(tr[k].rss1,tr[rc].sum+tr[lc].rss1);
        tr[k].max1=max(tr[lc].max1,tr[rc].max1);
        if(tr[lc].rp&&tr[rc].lp) tr[k].max1=max(tr[k].max1,tr[lc].rss1+tr[rc].lss1);
    }
    void pushdown(int k){
        if(~tr[k].tag){
    //        tr[k].rev=0;
            if(tr[k].tag){
                tr[lc].lp=tr[lc].rp=1;
                tr[lc].lss1=tr[lc].rss1=tr[lc].max1=tr[lc].sum=tr[lc].r-tr[lc].l+1;
                tr[lc].lss0=tr[lc].rss0=tr[lc].max0=0;
                
                tr[rc].lp=tr[rc].rp=1;
                tr[rc].lss1=tr[rc].rss1=tr[rc].max1=tr[rc].sum=tr[rc].r-tr[rc].l+1;
                tr[rc].lss0=tr[rc].rss0=tr[rc].max0=0;
            }
            else{
                tr[lc].lp=tr[lc].rp=0;
                tr[lc].lss1=tr[lc].rss1=tr[lc].max1=tr[lc].sum=0;
                tr[lc].lss0=tr[lc].rss0=tr[lc].max0=tr[lc].r-tr[lc].l+1;
                
                tr[rc].lp=tr[rc].rp=0;
                tr[rc].lss1=tr[rc].rss1=tr[rc].max1=tr[rc].sum=0;
                tr[rc].lss0=tr[rc].rss0=tr[rc].max0=tr[rc].r-tr[rc].l+1;
            }
            tr[lc].tag=tr[rc].tag=tr[k].tag;tr[k].tag=-1;
    //        return ;
        }
        if(tr[k].rev){
            tr[k].rev=0;tr[lc].rev=1;tr[rc].rev=1;
            
            tr[lc].sum=tr[lc].r-tr[lc].l+1-tr[lc].sum;
            
            tr[lc].lp^=1;tr[lc].rp^=1;
            swap(tr[lc].max0,tr[lc].max1);
            swap(tr[lc].lss0,tr[lc].lss1);
            swap(tr[lc].rss0,tr[lc].rss1);
            
            tr[rc].sum=tr[rc].r-tr[rc].l+1-tr[rc].sum;
            tr[rc].lp^=1;tr[rc].rp^=1;
            swap(tr[rc].max0,tr[rc].max1);
            swap(tr[rc].lss0,tr[rc].lss1);
            swap(tr[rc].rss0,tr[rc].rss1);
        }
    }
    void deal(int k,int v){
        if(v){
            tr[k].lp=tr[k].rp=1;
            tr[k].sum=tr[k].max1=tr[k].lss1=tr[k].rss1=tr[k].r-tr[k].l+1;
            tr[k].max0=tr[k].lss0=tr[k].rss0=0;
        }
        else{
            tr[k].lp=tr[k].rp=0;
            tr[k].max0=tr[k].lss0=tr[k].rss0=tr[k].r-tr[k].l+1;
            tr[k].sum=tr[k].max1=tr[k].lss1=tr[k].rss1=0;
        }
    }
    void vpt(int k){
        if(tr[k].l==tr[k].r) return ;
        pushdown(k);
        vpt(lc);
        vpt(rc);
    }
    void build(int k,int l,int r){
        tr[k].l=l;tr[k].r=r;tr[k].tag=-1;
        if(l==r){
            tr[k].lp=tr[k].rp=a[l];
            tr[k].sum=tr[k].max1=tr[k].lss1=tr[k].rss1=(a[l]==1);
            tr[k].max0=tr[k].lss0=tr[k].rss0=(a[l]==0);
            return ;
        }
        int mid=l+r>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
        updata(k);
    }
    void cover(int k,int x,int y,int v){
        int l=tr[k].l,r=tr[k].r;
        if(l==x&&r==y){
            vpt(k);
            deal(k,v);
            if(l!=r) tr[k].tag=v;
            return ;
        }
        pushdown(k);
        int mid=l+r>>1;
        if(y<=mid) cover(lc,x,y,v);
        else if(x>mid) cover(rc,x,y,v);
        else cover(lc,x,mid,v),cover(rc,mid+1,y,v);
        updata(k);
    }
    void rever(int k,int x,int y){
        int l=tr[k].l,r=tr[k].r;
        if(l==x&&r==y){
            vpt(k);
            tr[k].sum=tr[k].r-tr[k].l+1-tr[k].sum;
            tr[k].lp^=1;tr[k].rp^=1;
            swap(tr[k].max0,tr[k].max1);
            swap(tr[k].lss0,tr[k].lss1);
            swap(tr[k].rss0,tr[k].rss1);
            if(l!=r) tr[k].rev=1;
            return ;
        }
        pushdown(k);
        int mid=l+r>>1;
        if(y<=mid) rever(lc,x,y);
        else if(x>mid) rever(rc,x,y);
        else rever(lc,x,mid),rever(rc,mid+1,y);
        updata(k);
    }
    int query_sum(int k,int x,int y){
        int l=tr[k].l,r=tr[k].r;
        if(l==x&&r==y) return tr[k].sum;
        pushdown(k);
        int mid=l+r>>1;
        if(y<=mid) return query_sum(lc,x,y);
        else if(x>mid) return query_sum(rc,x,y);
        else return 
            query_sum(lc,x,mid)+
            query_sum(rc,mid+1,y);
    }
    sgt query_max(int k,int x,int y){
        int l=tr[k].l,r=tr[k].r;
        if(l==x&&r==y) return tr[k];
        pushdown(k);
        int mid=l+r>>1;
        if(y<=mid) return query_max(lc,x,y);
        else if(x>mid) return query_max(rc,x,y);
        else{
            sgt k1=query_max(lc,x,mid);
            sgt k2=query_max(rc,mid+1,y);
            return merge(k1,k2);
        }
    }
    int main(){
        freopen("operation.in","r",stdin);
        freopen("operation.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=n;i++) a[i]=read();
        build(1,1,n);
        for(int i=1,opt,x,y;i<=m;i++){
            opt=read();x=read()+1;y=read()+1;
            if(opt<2) cover(1,x,y,opt);
            else if(opt==2) rever(1,x,y);
            else if(opt==3) printf("%d
    ",query_sum(1,x,y));
            else{
                s=query_max(1,x,y);
                printf("%d
    ",s.max1);
            }
        }
        return 0;
    }
    50分sgtTLE
    #include<cstdio>
    #include<iostream>
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int N=1000100;
    int n,m,a[N];
    int sum(int l,int r){
        int res=0;
        for(int i=l;i<=r;i++) res+=a[i];
        return res;
    }
    int conti(int l,int r){
        int res=0;
        for(int i=l,j=i;i<=r;){
            if(a[i]){
                for(j=i+1;j<=r;j++){
                    if(!a[j]) break;
                }
                res=max(res,j-i);
                i=j+1;
            }
            else i++;
        }
        return res;
    }
    void out(){
        for(int j=0;j<n;j++) printf("%d ",a[j]);printf("
    
    
    ");
    }
    int main(){
        n=read();m=read();
        for(int i=0;i<n;i++) a[i]=read();
        for(int i=0,opt,x,y;i<m;i++){
            opt=read();x=read();y=read();
            if(opt==0){
                for(int j=x;j<=y;j++) a[j]=0;
            } 
            if(opt==1){
                for(int j=x;j<=y;j++) a[j]=1;
            } 
            if(opt==2){
                for(int j=x;j<=y;j++) a[j]^=1;
            } 
            if(opt==3){
                printf("%d
    ",sum(x,y));
            } 
            if(opt==4){
                printf("%d
    ",conti(x,y));
            } 
        }
        return 0;
    }
    90分暴力
    /*
    本题的难度在于标记的下放。
    下面说一下我的做法: 
    1.覆盖标记:直接打上就好了
    2.取反标记: 
        <1>如果有tag标记,将tag标记取反,退出.
        <2>如果有rev标记,直接退出
        <3>无标记,打上rev标记,退出
    维护:
    sum(当前区间和),lss1(区间从左端点连续1的长度),rss1(区间从右端点连续1的长度),sc1(区间连续1的长度)
    lss0,rss0,sc0同理。tag(覆盖标记和取反标记整一起了) 
    */
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int N=1e5+5;
    const int M=505;
    int a[N],bl[N],n,m,size;
    int tag[M],lss0[M],rss0[M],sc0[M],lss1[M],rss1[M],sc1[M],sum[M];
    void init(int i){
        tag[i]=-1;lss0[i]=rss0[i]=sc0[i]=lss1[i]=rss1[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) lss0[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) rss0[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) lss1[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) rss1[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 cover(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) lss1[i]=rss1[i]=sc1[i]=sum[i]=size,lss0[i]=rss0[i]=sc0[i]=0;
            else lss1[i]=rss1[i]=sc1[i]=sum[i]=0,lss0[i]=rss0[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 rever(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(lss0[i],lss1[i]);swap(rss0[i],rss1[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 query_sum(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 query_num(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+=lss1[i];
            ans=max(ans,l);
            ans=max(ans,sc1[i]);
            if(lss1[i]!=size) l=rss1[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);
        for(int i=1,op,x,y;i<=m;i++){
            scanf("%d%d%d",&op,&x,&y);x++;y++;
            if(op==0) cover(x,y,0);
            if(op==1) cover(x,y,1);
            if(op==2) rever(x,y);
            if(op==3) printf("%d
    ",query_sum(x,y));
            if(op==4) printf("%d
    ",query_num(x,y));
        }
        return 0;
    }
  • 相关阅读:
    Element节点
    Document节点
    ParentNode接口,ChildNode接口
    NodeList接口,HTMLCollection接口
    Node接口
    DOM概述
    Promise对象
    定时器
    IT常用日语
    配置JavaWeb开发环境
  • 原文地址:https://www.cnblogs.com/shenben/p/6647535.html
Copyright © 2020-2023  润新知