题目传送门
。
解法:
线段树。
因为01要交换。
所以0和1的信息都要维护。
维护最长连续一段,总数,从左端点连续,从右端点连续。
然后打上覆盖和翻转标记。
不允许两种标记同时存在。
如果要打覆盖标记,那么翻转标记就没用了。
如果打翻转标记,那么覆盖标记取反就行。
代码实现:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node {int l,r,lc,rc,c[2],s[2],Lc[2],Rc[2],size,lazy,fz;}tr[210000];int trlen;
void bt(int l,int r) {
int now=++trlen;tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;
tr[now].c[1]=tr[now].c[0]=0;tr[now].s[1]=tr[now].s[0]=0;
tr[now].Lc[0]=tr[now].Lc[1]=0;tr[now].Rc[0]=tr[now].Rc[1]=0;
tr[now].size=r-l+1;tr[now].lazy=-1;tr[now].fz=0;
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 update(int now) {
int lc=tr[now].lc,rc=tr[now].rc;if(lc==-1)return ;
if(tr[now].lazy!=-1) {
int t=tr[now].lazy;
tr[lc].c[t]=tr[lc].size;tr[rc].c[t]=tr[rc].size;
tr[lc].c[1-t]=tr[rc].c[1-t]=0;
tr[lc].Lc[t]=tr[lc].Rc[t]=tr[lc].size;
tr[rc].Lc[t]=tr[rc].Rc[t]=tr[rc].size;
tr[lc].Lc[1-t]=tr[lc].Rc[1-t]=0;
tr[rc].Lc[1-t]=tr[rc].Rc[1-t]=0;
tr[lc].s[t]=tr[lc].size;tr[lc].s[1-t]=0;
tr[rc].s[t]=tr[rc].size;tr[rc].s[1-t]=0;
tr[lc].fz=tr[rc].fz=0;tr[lc].lazy=tr[rc].lazy=tr[now].lazy;tr[now].lazy=-1;
}if(tr[now].fz!=0) {
swap(tr[lc].c[0],tr[lc].c[1]);swap(tr[rc].c[0],tr[rc].c[1]);
swap(tr[lc].s[0],tr[lc].s[1]);swap(tr[rc].s[0],tr[rc].s[1]);
swap(tr[lc].Lc[0],tr[lc].Lc[1]);swap(tr[rc].Lc[0],tr[rc].Lc[1]);
swap(tr[lc].Rc[0],tr[lc].Rc[1]);swap(tr[rc].Rc[0],tr[rc].Rc[1]);
tr[lc].fz^=1;tr[rc].fz^=1;tr[now].fz=0;
if(tr[lc].fz==1&&tr[lc].lazy!=-1){tr[lc].lazy^=1;tr[lc].fz=0;}
if(tr[rc].fz==1&&tr[rc].lazy!=-1){tr[rc].lazy^=1;tr[rc].fz=0;}
}
}
void change(int now,int l,int r,int k) {
update(now);
if(tr[now].l==l&&tr[now].r==r) {
tr[now].c[k]=tr[now].size;tr[now].c[1-k]=0;
tr[now].s[k]=tr[now].size;tr[now].s[1-k]=0;
tr[now].Lc[k]=tr[now].Rc[k]=tr[now].size;
tr[now].Lc[1-k]=tr[now].Rc[1-k]=0;
tr[now].lazy=k;tr[now].fz=0;return ;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)change(lc,l,r,k);else if(l>mid)change(rc,l,r,k);
else {change(lc,l,mid,k);change(rc,mid+1,r,k);}
for(int i=0;i<=1;i++) {
tr[now].s[i]=tr[lc].s[i]+tr[rc].s[i];
if(tr[lc].Lc[i]==tr[lc].size)tr[now].Lc[i]=tr[lc].size+tr[rc].Lc[i];
else tr[now].Lc[i]=tr[lc].Lc[i];
if(tr[rc].Rc[i]==tr[rc].size)tr[now]. Rc[i]=tr[rc].size+tr[lc].Rc[i];
else tr[now].Rc[i]=tr[rc].Rc[i];
tr[now].c[i]=max(max(tr[lc].c[i],tr[rc].c[i]),tr[lc].Rc[i]+tr[rc].Lc[i]);
}
}
void fz(int now,int l,int r) {
update(now);
if(tr[now].l==l&&tr[now].r==r) {
swap(tr[now].c[0],tr[now].c[1]);swap(tr[now].s[0],tr[now].s[1]);
swap(tr[now].Lc[0],tr[now].Lc[1]);swap(tr[now].Rc[0],tr[now].Rc[1]);
tr[now].fz^=1;if(tr[now].lazy!=-1&&tr[now].fz==1)tr[now].lazy^=1,tr[now].fz=0;
return ;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)fz(lc,l,r);else if(l>mid)fz(rc,l,r);
else {fz(lc,l,mid);fz(rc,mid+1,r);}
for(int i=0;i<=1;i++) {
tr[now].s[i]=tr[lc].s[i]+tr[rc].s[i];
if(tr[lc].Lc[i]==tr[lc].size)tr[now].Lc[i]=tr[lc].size+tr[rc].Lc[i];
else tr[now].Lc[i]=tr[lc].Lc[i];
if(tr[rc].Rc[i]==tr[rc].size)tr[now].Rc[i]=tr[rc].size+tr[lc].Rc[i];
else tr[now].Rc[i]=tr[rc].Rc[i];
tr[now].c[i]=max(max(tr[lc].c[i],tr[rc].c[i]),tr[lc].Rc[i]+tr[rc].Lc[i]);
}
}
int find_sum(int now,int l,int r,int k) {
update(now);
if(tr[now].l==l&&tr[now].r==r)return tr[now].s[k];
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)return find_sum(lc,l,r,k);else if(l>mid)return find_sum(rc,l,r,k);
else return find_sum(lc,l,mid,k)+find_sum(rc,mid+1,r,k);
}
int find_max(int now,int l,int r,int k) {
update(now);
if(tr[now].l==l&&tr[now].r==r)return tr[now].c[k];
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)return find_max(lc,l,r,k);else if(l>mid)return find_max(rc,l,r,k);
else {
int t=max(find_max(lc,l,mid,k),find_max(rc,mid+1,r,k));
int tt=min(tr[lc].Rc[k],mid-l+1)+min(tr[rc].Lc[k],r-mid);
return max(tt,t);
}
}
int main() {
//freopen("1858.in","r",stdin);freopen("1858.out","w",stdout);
int n,m;scanf("%d%d",&n,&m);trlen=0;bt(1,n);
for(int i=1;i<=n;i++) {int k;scanf("%d",&k);change(1,i,i,k);}
while(m--) {
int t,x,y;scanf("%d%d%d",&t,&x,&y);x++;y++;
if(t<=1)change(1,x,y,t);
else if(t==2)fz(1,x,y);
else if(t==3)printf("%d\n",find_sum(1,x,y,1));
else printf("%d\n",find_max(1,x,y,1));
}
return 0;
}