3911的升级版
同时要做两种LAZY操作,一定要先做COVER,否则会WA,因为COVER可以覆盖之前的XOR
#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
#include "algorithm"
using namespace std;
struct comp
{
int l,r,mid;
int l1,l0; // 记录区间内从最左端起连续1和0个数
int r1,r0; // 记录区间内从最右端起连续1和0个数
int m1,m0; // 记录区间内最长连续1和0个数
int cover; // lazy操作的覆盖
int xor; // lazy操作的变换
int sum; // 区间内1的总数
} data[300005];
int max(int a,int b)
{
if (a<b) return b; else return a;
}
void PushUp(int k)
{
int ll,rr;
ll=data[k*2].r-data[k*2].l+1;
rr=data[k*2+1].r-data[k*2+1].l+1;
data[k].sum=data[k*2].sum+data[k*2+1].sum;
data[k].l1=data[k*2].l1;
if (data[k].l1==ll) data[k].l1+=data[k*2+1].l1;
data[k].l0=data[k*2].l0;
if (data[k].l0==ll) data[k].l0+=data[k*2+1].l0;
data[k].r1=data[k*2+1].r1;
if (data[k].r1==rr) data[k].r1+=data[k*2].r1;
data[k].r0=data[k*2+1].r0;
if (data[k].r0==rr) data[k].r0+=data[k*2].r0;
data[k].m1=max( max(data[k*2].m1,data[k*2+1].m1) , data[k*2].r1+data[k*2+1].l1);
data[k].m0=max( max(data[k*2].m0,data[k*2+1].m0) , data[k*2].r0+data[k*2+1].l0);
}
void build(int l,int r,int k)
{
int x;
data[k].l=l; data[k].r=r;
data[k].mid=(l+r)/2;
data[k].xor=0;
data[k].cover=-1;
if (l==r)
{
scanf("%d",&x);
if (x==1)
{
data[k].l1=data[k].r1=data[k].m1=1;
data[k].l0=data[k].r0=data[k].m0=0;
data[k].sum=1;
data[k].cover=1;
}
else
{
data[k].l1=data[k].r1=data[k].m1=0;
data[k].l0=data[k].r0=data[k].m0=1;
data[k].sum=0;
data[k].cover=0;
}
return ;
}
build(l,data[k].mid,k*2);
build(data[k].mid+1,r,k*2+1);
PushUp(k);
}
void PushDown(int k) // 重点是两种LAZY操作的顺序,必须先做COVER操作
{
int ll,rr;
if (data[k].l==data[k].r) return ;
ll=data[k*2].r-data[k*2].l+1;
rr=data[k*2+1].r-data[k*2+1].l+1;
if (data[k].cover!=-1)
{
data[k*2].cover=data[k*2+1].cover=data[k].cover;
data[k*2].xor=data[k*2+1].xor=0;
if (data[k].cover==1)
{
data[k*2].sum=ll;
data[k*2+1].sum=rr;
data[k*2].l1=data[k*2].r1=data[k*2].m1=ll;
data[k*2].l0=data[k*2].r0=data[k*2].m0=0;
data[k*2+1].l1=data[k*2+1].r1=data[k*2+1].m1=rr;
data[k*2+1].l0=data[k*2+1].r0=data[k*2+1].m0=0;
}
if (data[k].cover==0)
{
data[k*2].sum=data[k*2+1].sum=0;
data[k*2].l1=data[k*2].r1=data[k*2].m1=0;
data[k*2].l0=data[k*2].r0=data[k*2].m0=ll;
data[k*2+1].l1=data[k*2+1].r1=data[k*2+1].m1=0;
data[k*2+1].l0=data[k*2+1].r0=data[k*2+1].m0=rr;
}
data[k].cover=-1;
}
if (data[k].xor%2==1)
{
data[k].xor=0;
data[k*2].xor++;
data[k*2+1].xor++;
data[k*2].sum=ll-data[k*2].sum;
data[k*2+1].sum=rr-data[k*2+1].sum;
swap(data[k*2].l1,data[k*2].l0);
swap(data[k*2].r1,data[k*2].r0);
swap(data[k*2].m1,data[k*2].m0);
swap(data[k*2+1].l1,data[k*2+1].l0);
swap(data[k*2+1].r1,data[k*2+1].r0);
swap(data[k*2+1].m1,data[k*2+1].m0);
}
}
void update(int l,int r,int k,int op)
{
int le;
PushDown(k);
if (data[k].l==l && data[k].r==r )
{
le=data[k].r-data[k].l+1;
if (op==0)
{
data[k].cover=0;
data[k].sum=0;
data[k].l1=data[k].r1=data[k].m1=0;
data[k].l0=data[k].r0=data[k].m0=le;
data[k].xor=0;
}
if (op==1)
{
data[k].cover=1;
data[k].sum=le;
data[k].l1=data[k].r1=data[k].m1=le;
data[k].l0=data[k].r0=data[k].m0=0;
data[k].xor=0;
}
if (op==2)
{
if (data[k].cover!=-1) data[k].cover=(data[k].cover+1)%2;
data[k].sum=le-data[k].sum;
swap(data[k].l1,data[k].l0);
swap(data[k].r1,data[k].r0);
swap(data[k].m1,data[k].m0);
data[k].xor++;
}
return ;
}
if (r<=data[k].mid) update(l,r,k*2,op);
else
if (l>data[k].mid) update(l,r,k*2+1,op);
else
{
update(l,data[k].mid,k*2,op);
update(data[k].mid+1,r,k*2+1,op);
}
PushUp(k);
}
int query(int l,int r,int k,int op)
{
int aa,bb,ll,rr;
if (data[k].l==l && data[k].r==r)
{
if (op==3) return data[k].sum;
else return data[k].m1;
}
PushDown(k);
if (r<=data[k].mid) return query(l,r,k*2,op);
else
if (l>data[k].mid) return query(l,r,k*2+1,op);
else
{
if (op==3) return query(l,data[k].mid,k*2,op)+query(data[k].mid+1,r,k*2+1,op);
else
{
aa=query(l,data[k].mid,k*2,op);
bb=query(data[k].mid+1,r,k*2+1,op);
ll=data[k*2].r1;
if (ll>data[k*2].r-l+1) ll=data[k*2].r-l+1;
rr=data[k*2+1].l1;
if (rr>r-data[k*2+1].l+1) rr=r-data[k*2+1].l+1;
return max(max(aa,bb),ll+rr);
}
}
}
int main()
{
int t,n,m,a,b,c;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&m);
build(1,n,1);
while (m--)
{
scanf("%d%d%d",&a,&b,&c);
b++;
c++;
if (a<=2) update(b,c,1,a);
else
printf("%d\n",query(b,c,1,a));
}
}
return 0;
}