题解:
线段树
每一次记录连续的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)]); } } }