题意:首先t表示有几组数据,然后n,m表示有n个数,m组操作,接着给你n个0或1的数字,,最后是操作0 a b表示把区间[a,b]里的数都变成0,1 a b把区间[a,b]里的数都变成1,2 a b表示把区间[a,b]里的1变成0,0变成1,3 a b表示[a,b]输出1的数目,4 a b表示输出最长的连续的1的数目。
区间合并的问题,因为最长的可能的除了可能出现在端点,还有可能出现在区间合并时,两边的连续的加起来。除了这个之外,还要注意,我们设置两个延迟标记,一个用来标记操作0、1,一个用来标记操作2,如果我们在进行操作0、1的更新的时候,如果有遇到操作2的标记,那么没必要往下更新标记2(因为会把操作2覆盖了),但是如果是进行操作2的更新,遇到操作0、1的更新,我们要往下更新。
因为有涉及到将0变成1,将1变成0的操作,所以我们除了记录端点处连续的1的长度,区间内1的数目,区间内最长的连续的1的数目之外,我们还要记录关于0相同的信息,这样,当有置反操作的时候,我们简单地交换对应的0和1的信息就可以了。
/*代码风格更新后 */
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int N=100005;
struct node
{
int lft,rht;
int lmx_0,rmx_0,mx_0,sum_0;
int lmx_1,rmx_1,mx_1,sum_1;
int flag_set,flag_rev;
int len(){return rht-lft+1;}
int mid(){return MID(lft,rht);}
void set_0(int a){ lmx_0=rmx_0=mx_0=sum_0=a; }
void set_1(int a){ lmx_1=rmx_1=mx_1=sum_1=a; }
void init()
{
set_0(0); set_1(0);
flag_rev=0; flag_set=-1;
}
void fun(int valu)
{
if(valu==0)
{
flag_set=0; flag_rev=0;
set_0(len()); set_1(0);
}
else if(valu==1)
{
flag_set=1; flag_rev=0;
set_0(0); set_1(len());
}
else
{
swap(lmx_0,lmx_1); swap(rmx_0,rmx_1);
swap(mx_0,mx_1); swap(sum_0,sum_1);
flag_rev^=1;
}
}
};
int y[N],n,m;
struct Segtree
{
node tree[N*4];
void down(int ind)
{
if(tree[ind].flag_set!=-1)
{
tree[LL(ind)].fun(tree[ind].flag_set);
tree[RR(ind)].fun(tree[ind].flag_set);
tree[ind].flag_set=-1;
}
if(tree[ind].flag_rev)
{
tree[LL(ind)].fun(2);
tree[RR(ind)].fun(2);
tree[ind].flag_rev=0;
}
}
void up(node &a,node &b,node &c)
{
a.lmx_0=b.lmx_0; a.rmx_0=c.rmx_0;
a.lmx_1=b.lmx_1; a.rmx_1=c.rmx_1;
a.sum_0=b.sum_0+c.sum_0; a.sum_1=b.sum_1+c.sum_1;
a.mx_0=max(b.rmx_0+c.lmx_0,max(b.mx_0,c.mx_0));
a.mx_1=max(b.rmx_1+c.lmx_1,max(b.mx_1,c.mx_1));
if(b.len()==b.lmx_0) a.lmx_0+=c.lmx_0;
if(b.len()==b.lmx_1) a.lmx_1+=c.lmx_1;
if(c.len()==c.rmx_0) a.rmx_0+=b.rmx_0;
if(c.len()==c.rmx_1) a.rmx_1+=b.rmx_1;
}
void build(int lft,int rht,int ind)
{
tree[ind].lft=lft; tree[ind].rht=rht;
tree[ind].init();
if(lft==rht)
{
if(y[lft]==1) tree[ind].set_0(0),tree[ind].set_1(1);
else tree[ind].set_0(1),tree[ind].set_1(0);
}
else
{
int mid=tree[ind].mid();
build(lft,mid,LL(ind));
build(mid+1,rht,RR(ind));
up(tree[ind],tree[LL(ind)],tree[RR(ind)]);
}
}
void updata(int st,int ed,int ind,int valu)
{
int lft=tree[ind].lft,rht=tree[ind].rht;
if(st<=lft&&rht<=ed) tree[ind].fun(valu);
else
{
down(ind);
int mid=tree[ind].mid();
if(st<=mid) updata(st,ed,LL(ind),valu);
if(ed> mid) updata(st,ed,RR(ind),valu);
up(tree[ind],tree[LL(ind)],tree[RR(ind)]);
}
}
int query(int st,int ed,int ind,int type)
{
int lft=tree[ind].lft,rht=tree[ind].rht;
if(st<=lft&&rht<=ed)
{
if(type==3) return tree[ind].sum_1;
else return tree[ind].mx_1;
}
else
{
down(ind);
int mid=tree[ind].mid(),res;
if(ed<=mid) res=query(st,ed,LL(ind),type);
else if(st>mid) res=query(st,ed,RR(ind),type);
else
{
int tmp1=query(st,ed,LL(ind),type);
int tmp2=query(st,ed,RR(ind),type);
if(type==3) res=tmp1+tmp2;
else
{
int tmp3=min(tree[LL(ind)].rmx_1,tree[LL(ind)].rht-st+1);
int tmp4=min(tree[RR(ind)].lmx_1,ed-tree[RR(ind)].lft+1);
res=max(max(tmp1,tmp2),tmp3+tmp4);
}
}
up(tree[ind],tree[LL(ind)],tree[RR(ind)]);
return res;
}
}
}seg;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&y[i]);
seg.build(0,n-1,1);
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a<=2) seg.updata(b,c,1,a);
else printf("%d\n",seg.query(b,c,1,a));
}
}
return 0;
}
/*代码风格更新前*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=100005;
int y[N];
struct node
{
int left,right,co,flag;
int maxl_0,maxr_0,maxl_1,maxr_1;
int sum_0,sum_1,max_1,max_0;
int mid(){return left+(right-left)/2;}
int dis(){return right-left+1;}
void change(int a,int rev)
{
if(a==0)
{
maxl_0=maxr_0=sum_0=max_0=dis();
maxl_1=maxr_1=sum_1=max_1=0;
co=a; flag=0;
}
else if(a==1)
{
maxl_0=maxr_0=sum_0=max_0=0;
maxl_1=maxr_1=sum_1=max_1=dis();
co=a; flag=0;
}
if(rev)
{
swap(maxr_1,maxr_0); swap(maxl_0,maxl_1);
swap(max_0,max_1); swap(sum_0,sum_1);
flag^=1;
}
}
};
void unin(node &a,node &b,node &c)
{
a.maxl_0=b.maxl_0; a.maxr_0=c.maxr_0;
a.maxl_1=b.maxl_1; a.maxr_1=c.maxr_1;
a.sum_0=b.sum_0+c.sum_0; a.sum_1=b.sum_1+c.sum_1;
a.max_0=max(b.maxr_0+c.maxl_0,max(b.max_0,c.max_0));
a.max_1=max(b.maxr_1+c.maxl_1,max(b.max_1,c.max_1));
if(b.dis()==b.maxl_0) a.maxl_0+=c.maxl_0;
if(b.dis()==b.maxl_1) a.maxl_1+=c.maxl_1;
if(c.dis()==c.maxr_0) a.maxr_0+=b.maxr_0;
if(c.dis()==c.maxr_1) a.maxr_1+=b.maxr_1;
}
struct Segtree
{
node tree[N*4];
void build(int left,int right,int r)
{
tree[r].left=left; tree[r].right=right;
tree[r].maxl_0=tree[r].maxr_0=tree[r].maxl_1=tree[r].maxr_1=0;
tree[r].sum_0=tree[r].sum_1=tree[r].max_0=tree[r].max_1=0;
tree[r].flag=0; tree[r].co=-1;
if(left==right)
{
tree[r].change(y[left],0);
}
else
{
int mid=tree[r].mid();
build(left,mid,r*2); build(mid+1,right,r*2+1);
unin(tree[r],tree[r*2],tree[r*2+1]);
}
}
void updata(int be,int end,int r,int co)
{
if(be<=tree[r].left&&tree[r].right<=end)
{
if(co==0||co==1) tree[r].change(co,0);
else tree[r].change(-1,1);
}
else
{
if(tree[r].co!=-1||tree[r].flag)
{
tree[r*2].change(tree[r].co,tree[r].flag);
tree[r*2+1].change(tree[r].co,tree[r].flag);
tree[r].co=-1; tree[r].flag=0;
}
int mid=tree[r].mid();
if(be<=mid) updata(be,end,r*2,co);
if(end>mid) updata(be,end,r*2+1,co);
unin(tree[r],tree[r*2],tree[r*2+1]);
}
}
int query(int be,int end,int r,int co)
{
if(be<=tree[r].left&&tree[r].right<=end)
{
if(co==3) return tree[r].sum_1;
else return tree[r].max_1;
}
else
{
if(tree[r].co!=-1||tree[r].flag)
{
tree[r*2].change(tree[r].co,tree[r].flag);
tree[r*2+1].change(tree[r].co,tree[r].flag);
tree[r].co=-1; tree[r].flag=0;
}
int mid=tree[r].mid();
if(end<=mid) return query(be,end,r*2,co);
else if(be>mid) return query(be,end,r*2+1,co);
else
{
int max1=query(be,end,r*2,co);
int max2=query(be,end,r*2+1,co);
if(co==3) return max1+max2;
int max3=min(tree[r*2].right-be+1,tree[r*2].maxr_1)+min(end-tree[r*2+1].left+1,tree[r*2+1].maxl_1);
return max(max(max1,max2),max3);
}
}
}
}seg;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&y[i]);
seg.build(0,n-1,1);
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==0||a==1||a==2) seg.updata(b,c,1,a);
else printf("%d\n",seg.query(b,c,1,a));
//for(int j=0;j<n;j++) printf("%d ",seg.query(j,j,1,3)); puts("");
}
}
return 0;
}