#include<iostream>
#include<cstdio>
#include<cmath>
#define lu p<<1
#define ru p<<1|1
using namespace std;
int n,m,o,x,y,k,w[100005];
struct node{
int l,r,b,c,lb,lc,rb,rc,mb,mc,sum,add;
bool e;
}tr[400005],z;
void pushup(node& p,node L,node R)
{
p.b=L.b+R.b;
p.c=L.c+R.c;
if(L.c==0)
p.lb=L.b+R.lb;
else
p.lb=L.lb;
if(R.c==0)
p.rb=R.b+L.rb;
else
p.rb=R.rb;
if(L.b==0)
p.lc=L.c+R.lc;
else
p.lc=L.lc;
if(R.b==0)
p.rc=R.c+L.rc;
else
p.rc=R.rc;
p.mb=max(L.rb+R.lb,max(L.mb,R.mb));
p.mc=max(L.rc+R.lc,max(L.mc,R.mc));
}
void opr_0(int p)
{
tr[p].b=tr[p].lb=tr[p].rb=tr[p].mb=0;
tr[p].c=tr[p].lc=tr[p].rc=tr[p].mc=tr[p].sum;
tr[p].add=tr[p].e=0;
}
void opr_1(int p)
{
tr[p].c=tr[p].lc=tr[p].rc=tr[p].mc=0;
tr[p].b=tr[p].lb=tr[p].rb=tr[p].mb=tr[p].sum;
tr[p].add=1;
tr[p].e=0;
}
void opr_2(int p)
{
swap(tr[p].b,tr[p].c);
swap(tr[p].lb,tr[p].lc);
swap(tr[p].rb,tr[p].rc);
swap(tr[p].mb,tr[p].mc);
tr[p].e^=1;
}
void pushdown(int p)
{
if(tr[p].add==0)
{
opr_0(lu);
opr_0(ru);
}
if(tr[p].add==1)
{
opr_1(lu);
opr_1(ru);
}
if(tr[p].e)
{
opr_2(lu);
opr_2(ru);
}
tr[p].add=-1;
tr[p].e=0;
}
void build(int p,int x,int y)
{
tr[p]={x,y,w[x],w[x],w[x],w[x],w[x]^1,w[x]^1,w[x]^1,w[x]^1,y-x+1,-1,0};
if(x==y)
return;
int m=x+y>>1;
build(lu,x,m);
build(ru,m+1,y);
pushup(tr[p],tr[lu],tr[ru]);
}
void update(int p,int x,int y,int k)
{
if(x>tr[p].r||y<tr[p].l)
return;
if(x<=tr[p].l&&tr[p].r<=y)
{
if(k==0)
opr_0(p);
if(k==1)
opr_1(p);
if(k==2)
opr_2(p);
return;
}
pushdown(p);
int m=tr[p].l+tr[p].r>>1;
update(lu,x,y,k);
update(ru,x,y,k);
pushup(tr[p],tr[lu],tr[ru]);
}
node query(int p,int x,int y)
{
if(x>tr[p].r||y<tr[p].l)
return {};
if(x<=tr[p].l&&tr[p].r<=y)
return tr[p];
pushdown(p);
node z;
pushup(z,query(lu,x,y),query(ru,x,y));
return z;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",w+i);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&o,&x,&y);
x++;
y++;
if(o<=2)
update(1,x,y,o);
else
{
z=query(1,x,y);
if(o==3)
printf("%d\n",z.b);
else
printf("%d\n",z.mb);
}
}
return 0;
}