rt
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int n,m,a[N],tag[N];
struct node{
int sum0,sum1,lst0,lst1,rst0,rst1,continuous0,continuous1;
}tree[N<<2];
node operator + (node a,node b){
node c;
c.sum0=a.sum0+b.sum0;
c.sum1=a.sum1+b.sum1;
c.lst0=a.lst0+(a.sum1?0:b.lst0);
c.lst1=a.lst1+(a.sum0?0:b.lst1);
c.rst0=b.rst0+(b.sum1?0:a.rst0);
c.rst1=b.rst1+(b.sum0?0:a.rst1);
c.continuous0=max(a.rst0+b.lst0,max(a.continuous0,b.continuous0));
c.continuous1=max(a.rst1+b.lst1,max(a.continuous1,b.continuous1));
return c;
}
void pushdown(int l,int r,int rt){
int mid=(l+r)>>1;
if(tag[rt]==1){
tree[rt<<1].continuous1=tree[rt<<1].lst1=tree[rt<<1].rst1=tree[rt<<1].sum1=0;
tree[rt<<1].continuous0=tree[rt<<1].lst0=tree[rt<<1].rst0=tree[rt<<1].sum0=mid-l+1;
tree[rt<<1|1].continuous1=tree[rt<<1|1].lst1=tree[rt<<1|1].rst1=tree[rt<<1|1].sum1=0;
tree[rt<<1|1].continuous0=tree[rt<<1|1].lst0=tree[rt<<1|1].rst0=tree[rt<<1|1].sum0=r-mid;
tag[rt<<1]=tag[rt];
tag[rt<<1|1]=tag[rt];
tag[rt]=0;
}
else if(tag[rt]==2){
tree[rt<<1].continuous0=tree[rt<<1].lst0=tree[rt<<1].rst0=tree[rt<<1].sum0=0;
tree[rt<<1].continuous1=tree[rt<<1].lst1=tree[rt<<1].rst1=tree[rt<<1].sum1=mid-l+1;
tree[rt<<1|1].continuous0=tree[rt<<1|1].lst0=tree[rt<<1|1].rst0=tree[rt<<1|1].sum0=0;
tree[rt<<1|1].continuous1=tree[rt<<1|1].lst1=tree[rt<<1|1].rst1=tree[rt<<1|1].sum1=r-mid;
tag[rt<<1]=tag[rt];
tag[rt<<1|1]=tag[rt];
tag[rt]=0;
}
else if(tag[rt]==3){
swap(tree[rt<<1].continuous0,tree[rt<<1].continuous1);
swap(tree[rt<<1].lst0,tree[rt<<1].lst1);
swap(tree[rt<<1].rst0,tree[rt<<1].rst1);
swap(tree[rt<<1].sum0,tree[rt<<1].sum1);
swap(tree[rt<<1|1].continuous0,tree[rt<<1|1].continuous1);
swap(tree[rt<<1|1].lst0,tree[rt<<1|1].lst1);
swap(tree[rt<<1|1].rst0,tree[rt<<1|1].rst1);
swap(tree[rt<<1|1].sum0,tree[rt<<1|1].sum1);
tag[rt<<1]=3;
tag[rt<<1|1]=3;
tag[rt]=0;
}
}
void build(int l,int r,int rt){
if(l==r){
if(a[l]==1){
tree[rt].continuous1=tree[rt].sum1=tree[rt].lst1=tree[rt].rst1=1;
}
else{
tree[rt].continuous0=tree[rt].sum0=tree[rt].lst0=tree[rt].rst0=1;
}
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void updateall0(int l,int r,int L,int R,int rt){
// cout<<"----------------- "<<l<<" "<<r<<" "<<rt<<endl;
if(L<=l&&r<=R){
// cout<<"yes"<<endl;
tree[rt].lst1=tree[rt].sum1=tree[rt].rst1=tree[rt].continuous1=0;
tree[rt].lst0=tree[rt].sum0=tree[rt].rst0=tree[rt].continuous0=r-l+1;
tag[rt]=1;
return;
}
pushdown(l,r,rt);
int mid=(l+r)>>1;
if(L<=mid)updateall0(l,mid,L,R,rt<<1);
if(R>mid)updateall0(mid+1,r,L,R,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void updateall1(int l,int r,int L,int R,int rt){
if(L<=l&&r<=R){
tree[rt].lst1=tree[rt].sum1=tree[rt].rst1=tree[rt].continuous1=r-l+1;
//cout<<l<<" "<<r<<" "<<rt<<endl;
tree[rt].lst0=tree[rt].sum0=tree[rt].rst0=tree[rt].continuous0=0;
tag[rt]=2;
return;
}
pushdown(l,r,rt);
int mid=(l+r)>>1;
if(L<=mid)updateall1(l,mid,L,R,rt<<1);
if(R>mid)updateall1(mid+1,r,L,R,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void updatexor(int l,int r,int L,int R,int rt){
if(L<=l&&r<=R){
swap(tree[rt].continuous0,tree[rt].continuous1);
swap(tree[rt].lst0,tree[rt].lst1);
swap(tree[rt].rst0,tree[rt].rst1);
swap(tree[rt].sum0,tree[rt].sum1);
if(tag[rt]==1)tag[rt]=2;
else if(tag[rt]==2)tag[rt]=1;
else tag[rt]=3;
return;
}
pushdown(l,r,rt);
int mid=(l+r)>>1;
if(L<=mid)updatexor(l,mid,L,R,rt<<1);
if(R>mid)updatexor(mid+1,r,L,R,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int querysum(int l,int r,int L,int R,int rt){
if(L<=l&&r<=R){
//cout<<l<<" "<<r<<" "<<rt<<" "<<tree[rt].sum1<<endl;
return tree[rt].sum1;
}
pushdown(l,r,rt);
int res=0;
int mid=(l+r)>>1;
if(L<=mid)res+=querysum(l,mid,L,R,rt<<1);
if(R>mid)res+=querysum(mid+1,r,L,R,rt<<1|1);
return res;
}
node querycontinuous(int l,int r,int L,int R,int rt){
if(L<=l&&r<=R){
return tree[rt];
}
pushdown(l,r,rt);
int res=0;
int mid=(l+r)>>1;
node tmp={0,0,0,0,0,0,0,0},tmp2={0,0,0,0,0,0,0,0};
if(L<=mid){
tmp=querycontinuous(l,mid,L,R,rt<<1);
//res=max(res,tmp.continuous1);
}
if(R>mid){
tmp2=querycontinuous(mid+1,r,L,R,rt<<1|1);
//res=max(res,tmp2.continuous1);
}
//res=max(res,tmp.rst1+tmp2.lst1);
node re=tmp+tmp2;
return re;
}
/*void print(int l,int r,int rt){
pushdown(l,r,rt);
cout<<rt<<" "<<l<<" "<<r<<" "<<tree[rt].sum0<<" "<<tree[rt].sum1<<" "<<tree[rt].lst0<<" "<<tree[rt].lst1<<" "<<tree[rt].rst0<<" "<<tree[rt].rst1<<" "<<tree[rt].continuous0<<" "<<tree[rt].continuous1<<endl;
if(l==r){
//cout<<"---------------"<<l<<" "<<r<<" "<<tree[rt].sum0<<" "<<tree[rt].sum1<<" "<<tree[rt].lst0<<" "<<tree[rt].lst1<<" "<<tree[rt].rst0<<" "<<tree[rt].rst1<<" "<<tree[rt].continuous0<<" "<<tree[rt].continuous1<<endl;
return;
}
int mid=(l+r)>>1;
print(l,mid,rt<<1);
print(mid+1,r,rt<<1|1);
} */
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,n,1);
while(m--){
int pos,x,y;
cin>>pos>>x>>y;
x++,y++;
if(pos==0){
updateall0(1,n,x,y,1);
}
else if(pos==1){
updateall1(1,n,x,y,1);
}
else if(pos==2){
updatexor(1,n,x,y,1);
}
else if(pos==3){
cout<<querysum(1,n,x,y,1)<<endl;
}
else{
cout<<querycontinuous(1,n,x,y,1).continuous1<<endl;
}
//print(1,n,1);
}
return 0;
}