题意:
给定长度为n的,由0,和1组成的序列,进行以下5种操作。
1)0 a b,将[a,b]区间内所有数变为0
2)1 a b,将[a,b]区间内所有数变为1
3)2 a b,将[a,b]区间内所以1变为0,所有0变为1.
4)3 a b,输出[a,b]区间内1的个数。
5)4 a b,输出[a,b]区间内连续1的最大长度。
题解:
建线段树,其中结点包括:
len:区间长度。
pre0:最长前缀连续0的长度。
aft0:最长后缀连续0的长度。
maxv0:最长连续0的长度。
pre1,aft1,maxv1与上同,表示连续1.
sum:表示区间内的所有数和,也就是区间内1的个数。
setv:懒惰标记,分4种,-1表示无,0表示变0操作,1表示变1操作,2表示异或操作。
问题主要在异或操作上,每次以后的时候,(pre0,aft0,maxv0)和(pre1,aft1,maxv1)交换即可(因为0都变成了1,1都变成了0)。
注意:这里的标记不是覆盖型的。。我就在这死的惨惨的。。每次遇到标记的时候要判断现有标记和新增标记,结合得到一个新的标记。
代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
using namespace std;
const int maxn=1e5+10;
struct node{
int l,r,len;
int pre0,aft0,maxv0;
int pre1,aft1,maxv1;
int sum;
int setv;
}e[maxn*4];
int f[maxn];
void push_up(int c)
{
if(e[2*c].pre0==e[2*c].len)e[c].pre0=e[2*c].pre0+e[2*c+1].pre0;
else e[c].pre0=e[2*c].pre0;
if(e[2*c+1].aft0==e[2*c+1].len)e[c].aft0=e[2*c+1].aft0+e[2*c].aft0;
else e[c].aft0=e[2*c+1].aft0;
e[c].maxv0=max(max(e[2*c].maxv0,e[2*c+1].maxv0),e[2*c].aft0+e[2*c+1].pre0);
if(e[2*c].pre1==e[2*c].len)e[c].pre1=e[2*c].pre1+e[2*c+1].pre1;
else e[c].pre1=e[2*c].pre1;
if(e[2*c+1].aft1==e[2*c+1].len)e[c].aft1=e[2*c+1].aft1+e[2*c].aft1;
else e[c].aft1=e[2*c+1].aft1;
e[c].maxv1=max(max(e[2*c].maxv1,e[2*c+1].maxv1),e[2*c].aft1+e[2*c+1].pre1);
e[c].sum=e[2*c].sum+e[2*c+1].sum;
}
void push_down(int c)
{
if(e[c].setv!=-1)
{
if(e[c].setv==0)
{
e[2*c].pre0=e[2*c].aft0=e[2*c].maxv0=e[2*c].r-e[2*c].l+1;
e[2*c].pre1=e[2*c].aft1=e[2*c].maxv1=e[2*c].sum=0;
e[2*c+1].pre0=e[2*c+1].aft0=e[2*c+1].maxv0=e[2*c+1].r-e[2*c+1].l+1;
e[2*c+1].pre1=e[2*c+1].aft1=e[2*c+1].maxv1=e[2*c+1].sum=0;
}
else if(e[c].setv==1)
{
e[2*c].pre0=e[2*c].aft0=e[2*c].maxv0=0;
e[2*c].pre1=e[2*c].aft1=e[2*c].maxv1=e[2*c].sum=e[2*c].r-e[2*c].l+1;
e[2*c+1].pre0=e[2*c+1].aft0=e[2*c+1].maxv0=0;
e[2*c+1].pre1=e[2*c+1].aft1=e[2*c+1].maxv1=e[2*c+1].sum=e[2*c+1].r-e[2*c+1].l+1;
}
else
{
swap(e[2*c].pre0,e[2*c].pre1);
swap(e[2*c].aft0,e[2*c].aft1);
swap(e[2*c].maxv0,e[2*c].maxv1);
e[2*c].sum=e[2*c].r-e[2*c].l+1-e[2*c].sum;
swap(e[2*c+1].pre0,e[2*c+1].pre1);
swap(e[2*c+1].aft0,e[2*c+1].aft1);
swap(e[2*c+1].maxv0,e[2*c+1].maxv1);
e[2*c+1].sum=e[2*c+1].r-e[2*c+1].l+1-e[2*c+1].sum;
}
if(e[c].setv<2)e[2*c].setv=e[2*c+1].setv=e[c].setv;
else
{
if(e[2*c].setv==-1)e[2*c].setv=2;
else if(e[2*c].setv==0)e[2*c].setv=1;
else if(e[2*c].setv==1)e[2*c].setv=0;
else e[2*c].setv=-1;
if(e[2*c+1].setv==-1)e[2*c+1].setv=2;
else if(e[2*c+1].setv==0)e[2*c+1].setv=1;
else if(e[2*c+1].setv==1)e[2*c+1].setv=0;
else e[2*c+1].setv=-1;
}
e[c].setv=-1;
}
}
void build(int a,int b,int c)
{
if(a==b)
{
e[c].l=e[c].r=a;
e[c].len=1;
e[c].pre0=e[c].aft0=e[c].maxv0=(f[a]==1?0:1);
e[c].pre1=e[c].aft1=e[c].maxv1=(f[a]==1?1:0);
e[c].setv=-1;
e[c].sum=f[a];
return ;
}
int mid=(a+b)/2;
build(a,mid,2*c);
build(mid+1,b,2*c+1);
e[c].l=a;e[c].r=b;e[c].len=b-a+1;
push_up(c);
e[c].setv=-1;
}
void update(int a,int b,int c,int val)
{
// printf("%d %d\n",e[c].l,e[c].r);
if(e[c].l==a&&e[c].r==b)
{
if(val==0)
{
e[c].pre0=e[c].aft0=e[c].maxv0=b-a+1;
e[c].pre1=e[c].aft1=e[c].maxv1=0;
e[c].sum=0;
}
else if(val==1)
{
e[c].pre0=e[c].aft0=e[c].maxv0=0;
e[c].pre1=e[c].aft1=e[c].maxv1=b-a+1;
e[c].sum=b-a+1;
}
else if(val==2)
{
swap(e[c].pre0,e[c].pre1);
swap(e[c].aft0,e[c].aft1);
swap(e[c].maxv0,e[c].maxv1);
e[c].sum=b-a+1-e[c].sum;
}
if(val==0||val==1)e[c].setv=val;
else
{
if(e[c].setv==-1)e[c].setv=2;
else if(e[c].setv==0)e[c].setv=1;
else if(e[c].setv==1)e[c].setv=0;
else e[c].setv=-1;
}
//printf("**%d %d %d\n",e[c].l,e[c].r,e[c].sum);
return ;
}
push_down(c);
int mid=(e[c].l+e[c].r)/2;
if(b<=mid)update(a,b,2*c,val);
else if(a>mid)update(a,b,2*c+1,val);
else
{
update(a,mid,2*c,val);
update(mid+1,b,2*c+1,val);
}
push_up(c);
//printf("*%d %d %d\n",e[c].l,e[c].r,e[c].sum);
}
node query(int a,int b,int c)
{
if(e[c].l==a&&e[c].r==b)
{
return e[c];
}
push_down(c);
int mid=(e[c].l+e[c].r)/2;
if(b<=mid)return query(a,b,2*c);
else if(a>mid)return query(a,b,2*c+1);
else
{
node o,p,q;
p=query(a,mid,2*c);q=query(mid+1,b,2*c+1);
if(p.pre1==p.len)o.pre1=p.pre1+q.pre1;
else o.pre1=p.pre1;
if(q.aft1==q.len)o.aft1=q.aft1+p.aft1;
else o.aft1=q.aft1;
o.maxv1=max(max(p.maxv1,q.maxv1),p.aft1+q.pre1);
o.sum=p.sum+q.sum;
o.len=p.len+q.len;
return o;
}
}
int main()
{
//freopen("D:\\in.txt","r",stdin);
//freopen("D:\\out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int i,j,k,n,m,a,b,c;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&f[i]);
build(1,n,1);
node ans;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
b++;c++;
if(a<3)update(b,c,1,a);
else
{
ans=query(b,c,1);
if(a==3)printf("%d\n",ans.sum);
else printf("%d\n",ans.maxv1);
}
}
}
return 0;
}
/*
1
10 10
0 0 1 1 1 0 0 0 0 0
2 1 6
2 2 6
2 1 3
4 1 6
1
1
10 10
0 0 0 0 0 0 0 1 0 1
2 4 7
1 1 6
2 0 5
2 4 6
3 2 4
3 1 5
3 2 2
1
2
0
*/