#include<stdio.h>
#define MAXN 100000
struct node{
int sum;
int lmax1,rmax1,tmax1;
int lmax0,rmax0,tmax0;
int cnt;
int color;
}tree[MAXN*4];
int Total,Interval_max;
int max(int a,int b)
{ return a>b?a:b;}
void update_info(int l,int r,int mid,int idx)
{
tree[idx].sum=tree[idx*2].sum+tree[idx*2+1].sum;
tree[idx].lmax1=tree[idx*2].lmax1;
if(tree[idx*2].lmax1==(mid-l+1)) tree[idx].lmax1+=tree[idx*2+1].lmax1;
tree[idx].rmax1=tree[idx*2+1].rmax1;
if(tree[idx*2+1].rmax1==(r-mid)) tree[idx].rmax1+=tree[idx*2].rmax1;
tree[idx].tmax1=max(tree[idx*2].tmax1,tree[idx*2+1].tmax1);
tree[idx].tmax1=max(tree[idx].tmax1,tree[idx*2].rmax1+tree[idx*2+1].lmax1);
tree[idx].lmax0=tree[idx*2].lmax0;
if(tree[idx*2].lmax0==(mid-l+1)) tree[idx].lmax0+=tree[idx*2+1].lmax0;
tree[idx].rmax0=tree[idx*2+1].rmax0;
if(tree[idx*2+1].rmax0==(r-mid)) tree[idx].rmax0+=tree[idx*2].rmax0;
tree[idx].tmax0=max(tree[idx*2].tmax0,tree[idx*2+1].tmax0);
tree[idx].tmax0=max(tree[idx].tmax0,tree[idx*2].rmax0+tree[idx*2+1].lmax0);
}
void build(int l,int r,int idx)
{
tree[idx].color=0;
if(l==r)
{
scanf("%idx",&tree[idx].tmax1);
tree[idx].lmax1=tree[idx].rmax1=tree[idx].tmax1;
tree[idx].cnt=tree[idx].tmax1;
tree[idx].sum=tree[idx].tmax1;
tree[idx].lmax0=tree[idx].rmax0=tree[idx].tmax0=1-tree[idx].tmax1;
return ;
}
int m;
tree[idx].cnt=-1;
m=(l+r)/2;
build(l,m,idx*2);
build(m+1,r,idx*2+1);
update_info(l,r,m,idx);
}
void push_down(int l,int r,int m,int idx)
{
if(tree[idx].cnt>=0)
{
tree[idx].cnt^=tree[idx].color;
tree[idx*2].cnt=tree[idx*2+1].cnt=tree[idx].cnt;
tree[idx*2].color=0;tree[idx*2+1].color=0;
tree[idx*2].sum=tree[idx*2].lmax1=tree[idx*2].rmax1=tree[idx*2].tmax1=tree[idx].cnt*(m-l+1);
tree[idx*2].lmax0=tree[idx*2].rmax0=tree[idx*2].tmax0=(1-tree[idx].cnt)*(m-l+1);
tree[idx*2+1].sum=tree[idx*2+1].lmax1=tree[idx*2+1].rmax1=tree[idx*2+1].tmax1=tree[idx].cnt*(r-m);
tree[idx*2+1].lmax0=tree[idx*2+1].rmax0=tree[idx*2+1].tmax0=(1-tree[idx].cnt)*(r-m);
tree[idx].color=0;
tree[idx].cnt=-1;
return ;
}
if(tree[idx].color==1)
{
int t;
tree[idx*2].sum=m-l+1-tree[idx*2].sum;
t=tree[idx*2].rmax1;tree[idx*2].rmax1=tree[idx*2].rmax0;tree[idx*2].rmax0=t;
t=tree[idx*2].lmax1;tree[idx*2].lmax1=tree[idx*2].lmax0;tree[idx*2].lmax0=t;
t=tree[idx*2].tmax1;tree[idx*2].tmax1=tree[idx*2].tmax0;tree[idx*2].tmax0=t;
tree[idx*2+1].sum=r-m-tree[idx*2+1].sum;
t=tree[idx*2+1].rmax1;tree[idx*2+1].rmax1=tree[idx*2+1].rmax0;tree[idx*2+1].rmax0=t;
t=tree[idx*2+1].lmax1;tree[idx*2+1].lmax1=tree[idx*2+1].lmax0;tree[idx*2+1].lmax0=t;
t=tree[idx*2+1].tmax1;tree[idx*2+1].tmax1=tree[idx*2+1].tmax0;tree[idx*2+1].tmax0=t;
tree[idx*2].color^=1;
tree[idx*2+1].color^=1;
tree[idx].color=0;
}
}
void update(int a,int b,int cnt,int l,int r,int idx)
{
if(a<=l&&r<=b)
{
tree[idx].cnt=cnt;
tree[idx].color=0;
tree[idx].sum=tree[idx].lmax1=tree[idx].rmax1=tree[idx].tmax1=cnt*(r-l+1);
tree[idx].rmax0=tree[idx].lmax0=tree[idx].tmax0=(1-cnt)*(r-l+1);
return;
}
int mid=(l+r)/2;
push_down(l,r,mid,idx);
if(a<=mid) update(a,b,cnt,l,mid,idx*2);
if(b>mid) update(a,b,cnt,mid+1,r,idx*2+1);
update_info(l,r,mid,idx);
}
void update_xor(int a,int b,int l,int r,int idx)
{
if(a<=l&&r<=b)
{
int t;
tree[idx].color^=1;
tree[idx].sum=r-l+1-tree[idx].sum;
t=tree[idx].rmax1;tree[idx].rmax1=tree[idx].rmax0;tree[idx].rmax0=t;
t=tree[idx].lmax1;tree[idx].lmax1=tree[idx].lmax0;tree[idx].lmax0=t;
t=tree[idx].tmax1;tree[idx].tmax1=tree[idx].tmax0;tree[idx].tmax0=t;
return;
}
int m=(l+r)/2;
push_down(l,r,m,idx);
if(a<=m) update_xor(a,b,l,m,idx*2);
if(b>m) update_xor(a,b,m+1,r,idx*2+1);
update_info(l,r,m,idx);
}
void Query_sum(int a,int b,int l,int r,int idx)
{
if(a<=l&&r<=b)
{
Total+=tree[idx].sum;
return;
}
int mid=(l+r)/2;
push_down(l,r,mid,idx);
if(a<=mid) Query_sum(a,b,l,mid,idx*2);
if(b>mid) Query_sum(a,b,mid+1,r,idx*2+1);
update_info(l,r,mid,idx);
}
void Query_Interval(int a,int b,int l,int r,int idx)
{
if(a<=l&&r<=b)
{
if(Interval_max<tree[idx].tmax1) Interval_max=tree[idx].tmax1;
return;
}
int mid=(l+r)/2;
push_down(l,r,mid,idx);
if(a<=mid&&mid<b)
{
int s=0;
if((mid-a+1)>tree[idx*2].rmax1) s+=tree[idx*2].rmax1;
else
s+=mid-a+1;
if((b-mid)>tree[idx*2+1].lmax1) s+=tree[idx*2+1].lmax1;
else
s+=b-mid;
if(s>Interval_max) Interval_max=s;
}
if(a<=mid&&Interval_max<tree[idx*2].tmax1) Query_Interval(a,b,l,mid,idx*2);
if(b>mid&&Interval_max<tree[idx*2+1].tmax1) Query_Interval(a,b,mid+1,r,idx*2+1);
update_info(l,r,mid,idx);
}
int main()
{
int n,m,t;
int a,b,op;
scanf("%idx",&t);
while(t--)
{
scanf("%d %d",&n,&m);
n--;
build(0,n,1);
while(m--)
{
scanf("%d %d %d",&op,&a,&b);
if(op==0||op==1)
{
update(a,b,op,0,n,1);
}
if(op==2)
{
update_xor(a,b,0,n,1);
}
if(op==3)
{
Total=0;
Query_sum(a,b,0,n,1);
printf("%d\n",Total);
}
if(op==4)
{
Interval_max=0;
Query_Interval(a,b,0,n,1);
printf("%d\n",Interval_max);
}
}
}
return 0;
}