题意:给出几个操作。。。0 更新一段区间内的值全为0.
1跟新一段区间内全为1.
2一段区间内的值全部异或起来
3查询这段区间内1的个数。
4查询这段区间内连续1的个数。。。
这题简直操蛋。。。WA了20+次。。。
其实原理很简单,只要注意下异或覆盖和直接覆盖的先后顺序就可以,如果先异或后直接覆盖,则异或覆盖不存在了,反过来,异或覆盖是存在了。。。
一直以为是顺序出了问题。。队友一看。。。查询写错了,查询连续时。。居然直接无脑相加了。。。。
/*************************************************************************
> File Name: 3397.cpp
> Author: tjw
> Mail:
> Created Time: 2014年11月04日 星期二 15时35分30秒
************************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define lll (long long)
#define ls (k<<1)
#define rs (k<<1|1)
using namespace std;
const int MAXN=100010;
struct TREE
{
int l,r;
int mark,markxor;
int msum0,lsum0,rsum0;
int msum1,lsum1,rsum1;
int mmax0,mmax1;
int mid()
{
return (l+r)>>1;
}
}tree[MAXN<<2];
int num;
void pushup(int k,int m)
{
tree[k].mmax1=tree[k<<1].mmax1+tree[k<<1|1].mmax1;
tree[k].lsum1=tree[k<<1].lsum1;
if(tree[k<<1].lsum1==m-(m>>1))
tree[k].lsum1+=tree[k<<1|1].lsum1;
tree[k].rsum1=tree[k<<1|1].rsum1;
if(tree[k<<1|1].rsum1==(m>>1))
tree[k].rsum1+=tree[k<<1].rsum1;
tree[k].msum1=max(tree[k<<1].msum1,tree[k<<1|1].msum1);
tree[k].msum1=max(tree[k].msum1,tree[k<<1].rsum1+tree[k<<1|1].lsum1);
tree[k].mmax0=tree[k<<1].mmax0+tree[k<<1|1].mmax0;
tree[k].lsum0=tree[k<<1].lsum0;
if(tree[k<<1].lsum0==m-(m>>1))
tree[k].lsum0+=tree[k<<1|1].lsum0;
tree[k].rsum0=tree[k<<1|1].rsum0;
if(tree[k<<1|1].rsum0==(m>>1))
tree[k].rsum0+=tree[k<<1].rsum0;
tree[k].msum0=max(tree[k<<1].msum0,tree[k<<1|1].msum0);
tree[k].msum0=max(tree[k].msum0,tree[k<<1].rsum0+tree[k<<1|1].lsum0);
return;
}
void init(int rt,int m,int cmd){
tree[rt].lsum0=tree[rt].rsum0=tree[rt].msum0=tree[rt].mmax0=m*(1-cmd);
tree[rt].lsum1=tree[rt].rsum1=tree[rt].msum1=tree[rt].mmax1=m*cmd;
}
void change(int k){
swap(tree[k].lsum0,tree[k].lsum1);
swap(tree[k].rsum0,tree[k].rsum1);
swap(tree[k].msum0,tree[k].msum1);
swap(tree[k].mmax0,tree[k].mmax1);
}
void pushdown(int k,int m)
{
if(tree[k].mark!=-1)
{
tree[k<<1].mark=tree[k<<1|1].mark=tree[k].mark;
tree[k<<1].markxor=tree[k<<1|1].markxor=0;
init(k<<1,m-(m>>1),tree[k].mark);
init(k<<1|1,(m>>1),tree[k].mark);
tree[k].mark=-1;
}
else if(tree[k].markxor)
{
if(tree[k<<1].mark!=-1)
{
tree[k<<1].mark^=1;
init(k<<1,m-(m>>1),tree[k<<1].mark);
}
else
{
tree[k<<1].markxor^=1;
change(k<<1);
}
if(tree[k<<1|1].mark!=-1)
{
tree[k<<1|1].mark^=1;
init(k<<1|1,(m>>1),tree[k<<1|1].mark);
}
else
{
tree[k<<1|1].markxor^=1;
change(k<<1|1);
}
tree[k].markxor=0;
}
}
void build(int l,int r,int k)
{
tree[k].l=l;
tree[k].r=r;
tree[k].mark=-1;
tree[k].markxor=0;
if(l==r)
{
scanf("%d",&num);
tree[k].msum0=tree[k].lsum0=tree[k].rsum0=tree[k].mmax0=(num?0:1);
tree[k].msum1=tree[k].lsum1=tree[k].rsum1=tree[k].mmax1=(num?1:0);
return ;
}
int mid=tree[k].mid();
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
pushup(k,tree[k].r-tree[k].l+1);
}
void update(int l,int r,int op,int k)
{
if(tree[k].l>=l&&tree[k].r<=r)
{
if(op==2)
{
if(tree[k].mark!=-1)
{
tree[k].mark^=1;
init(k,tree[k].r-tree[k].l+1,tree[k].mark);
}
else
{
tree[k].markxor^=1;
change(k);
}
return;
}
tree[k].mark=op;
tree[k].markxor=0;
init(k,tree[k].r-tree[k].l+1,op);
return;
}
pushdown(k,tree[k].r-tree[k].l+1);
int mid=tree[k].mid();
if(r<=mid)
update(l,r,op,k<<1);
else if(l>mid)
update(l,r,op,k<<1|1);
else
{
update(l,mid,op,k<<1);
update(mid+1,r,op,k<<1|1);
}
pushup(k,tree[k].r-tree[k].l+1);
}
int query1(int l,int r,int k)
{
if(tree[k].l>=l&&tree[k].r<=r)
{
return tree[k].mmax1;
}
pushdown(k,tree[k].r-tree[k].l+1);
int mid=tree[k].mid();
if(r<=mid)
return query1(l,r,k<<1);
else if(l>mid)
return query1(l,r,k<<1|1);
else
{
int t1=query1(l,mid,k<<1);
int t2=query1(mid+1,r,k<<1|1);
return t1+t2;
}
}
int query2(int l,int r,int k)
{
if(tree[k].l>=l&&tree[k].r<=r)
{
return tree[k].msum1;
}
pushdown(k,tree[k].r-tree[k].l+1);
int mid=tree[k].mid();
if(r<=mid)
return query2(l,r,k<<1);
else if(l>mid)
return query2(l,r,k<<1|1);
else
{
int t1=query2(l,mid,k<<1);
int t2=query2(mid+1,r,k<<1|1);
int ans1=max(t1,t2);
int ans2=min(mid-l+1,tree[k<<1].rsum1)+min(r-mid,tree[k<<1|1].lsum1);
return max(ans1,ans2);
}
}
int main()
{
int t,n,m,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
build(0,n-1,1);
while(m--)
{
int a,b,op;
scanf("%d%d%d",&op,&a,&b);
if(op>2)
{
if(op==3)
{
printf("%d\n",query1(a,b,1));
}
else
printf("%d\n",query2(a,b,1));
}
else
{
update(a,b,op,1);
}
}
}
return 0;
}
/*
5
5 4
0 0 0 0 0
1 0 4
2 0 4
3 1 2
4 1 2
5 4
0 0 0 0 0
2 0 4
1 0 4
3 1 2
4 1 2
*/