题解:

线段树

每一次记录连续的1、0,、01个数

然后合并

代码:

#include<cstdio>  
#include<iostream>  
#define N 400005  
using namespace std;  
int n,m,i,nd=0,qd,root,opt,L,R;
int a[N],c[N][2],l[N],r[N],ml0[N];
int ml1[N],mr0[N],mr1[N],m1[N];
int m0[N],sum[N],tag0[N],tag1[N],rev[N];  
void update(int x)  
{  
    int lc=c[x][0],rc=c[x][1];  
    ml0[x]=ml0[lc];ml1[x]=ml1[lc];  
    mr0[x]=mr0[rc];mr1[x]=mr1[rc];  
    if (ml0[lc]==r[lc]-l[lc]+1)ml0[x]=ml0[lc]+ml0[rc];  
    if (ml1[lc]==r[lc]-l[lc]+1)ml1[x]=ml1[lc]+ml1[rc];  
    if (mr0[rc]==r[rc]-l[rc]+1)mr0[x]=mr0[rc]+mr0[lc];  
    if (mr1[rc]==r[rc]-l[rc]+1)mr1[x]=mr1[rc]+mr1[lc];  
    m1[x]=max(mr1[lc]+ml1[rc],max(m1[lc],m1[rc]));  
    m0[x]=max(mr0[lc]+ml0[rc],max(m0[lc],m0[rc]));  
    sum[x]=sum[lc]+sum[rc];  
}  
void mark0(int x)  
{  
    tag0[x]=1;tag1[x]=0;rev[x]=0;  
    ml0[x]=mr0[x]=m0[x]=r[x]-l[x]+1;  
    ml1[x]=mr1[x]=m1[x]=sum[x]=0;  
}  
void mark1(int x)  
{  
    tag1[x]=1;tag0[x]=0;rev[x]=0;  
    ml0[x]=mr0[x]=m0[x]=0;  
    ml1[x]=mr1[x]=m1[x]=sum[x]=r[x]-l[x]+1;  
}  
void markr(int x)  
{  
    rev[x]^=1;  
    swap(ml0[x],ml1[x]);
    swap(mr0[x],mr1[x]);  
    swap(m0[x],m1[x]);  
    sum[x]=r[x]-l[x]+1-sum[x];  
}  
void down(int x)  
{  
    if (tag0[x])mark0(c[x][0]),mark0(c[x][1]),tag0[x]=0;  
    if (tag1[x])mark1(c[x][0]),mark1(c[x][1]),tag1[x]=0;  
    if (rev[x])markr(c[x][0]),markr(c[x][1]),rev[x]=0;  
}  
void build(int &x,int ll,int rr)  
{  
    x=++nd;  
    l[x]=ll;r[x]=rr;  
    tag0[x]=tag1[x]=rev[x]=0;  
    if (ll==rr)  
     {  
        c[x][0]=c[x][1]=0;  
        ml0[x]=mr0[x]=m0[x]=(a[ll]==0);  
        ml1[x]=mr1[x]=m1[x]=sum[x]=(a[ll]==1);  
        return;  
     }  
    int mid=(ll+rr)/2;  
    build(c[x][0],ll,mid);
    build(c[x][1],mid+1,rr);  
    update(x);  
}  
void change(int x,int ll,int rr,int k)  
{  
    if (l[x]>rr||r[x]<ll)return;  
    down(x);  
    if (ll<=l[x]&&rr>=r[x])   
     {  
        if (k==0)mark0(x);
        else if(k==1)mark1(x);
        else markr(x);  
        return;  
     }  
    change(c[x][0],ll,rr,k);change(c[x][1],ll,rr,k);  
    update(x);  
}  
int query(int x,int ll,int rr)  
{  
    if (l[x]>rr||r[x]<ll)return 0;   
    down(x);  
    if (ll<=l[x]&&rr>=r[x])return sum[x];  
    return query(c[x][0],ll,rr)+query(c[x][1],ll,rr);  
}  
int query1(int x,int ll,int rr)  
{  
    down(x);  
    if (ll==l[x]&&rr==r[x])return x;  
    int mid=(l[x]+r[x])/2;  
    if (rr<=mid)return query1(c[x][0],ll,rr);  
    else if (ll>mid)return query1(c[x][1],ll,rr);else  
     {  
        int ans=++qd;  
        c[ans][0]=query1(c[x][0],ll,mid);c[ans][1]=query1(c[x][1],mid+1,rr);  
        update(ans);  
        return ans;  
     }  
}  
int main()  
{  
    scanf("%d%d",&n,&m);  
    for (i=1;i<=n;i++)scanf("%d",&a[i]);  
    build(root,1,n);  
    for (i=1;i<=m;i++)  
     {  
        scanf("%d%d%d",&opt,&L,&R);  
        if (opt==0||opt==1||opt==2) change(root,L+1,R+1,opt);  
        else  
         {  
            if (opt==3) printf("%d\n",query(root,L+1,R+1)); 
            else qd=nd,printf("%d\n",m1[query1(root,L+1,R+1)]);  
         }  
     }  
} 

 

posted on 2018-02-28 09:32  宣毅鸣  阅读(186)  评论(0编辑  收藏  举报