思路:和POJ3225有点像,但是多了那么些操作。对于区间1的个数和翻转情况,这都是可以用懒惰标记解决的。对于连续1的个数,需要区间合并。具体还是看注释吧。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 100005
struct SegTree
{
int l,r;
int olm,orm,omm;//分别为从左开始出现最多的1,从又开始最多1,区间最多连续1
int zlm,zrm,zmm;//同上,但是是0
int sum;//区间1的个数
bool flag;//翻转标记,当区间全部为0(sum==0)或者全部为1(sum==len())时,flag都是无意义的,标记为0,
SegTree() {}
int len()
{
return r-l+1;
}
} tree[maxn<<2];
int array[maxn];
void pushUp(SegTree *rt,SegTree *ls,SegTree *rs)//区间合并
{
rt->olm=ls->olm;
if(ls->olm==ls->len()) rt->olm=ls->olm+rs->olm;
rt->orm=rs->orm;
if(rs->orm==rs->len()) rt->orm=rs->orm+ls->orm;
rt->omm=max(rt->olm,rt->orm);
rt->omm=max(rt->omm,max(ls->omm,rs->omm));
rt->omm=max(rt->omm,ls->orm+rs->olm);
rt->zlm=ls->zlm;
if(ls->zlm==ls->len()) rt->zlm=ls->zlm+rs->zlm;
rt->zrm=rs->zrm;
if(rs->zrm==rs->len()) rt->zrm=rs->zrm+ls->zrm;
rt->zmm=max(rt->zlm,rt->zrm);
rt->zmm=max(rt->zmm,max(ls->zmm,rs->zmm));
rt->zmm=max(rt->zmm,ls->zrm+rs->zlm);
rt->sum=ls->sum+rs->sum;
}
inline void pushDown(int rt)//传递懒惰标记,更新左右孩子
{
if(tree[rt].sum==tree[rt].len()||tree[rt].sum==0)
{
int ls=rt<<1,rs=rt<<1|1;
tree[rt].flag=tree[ls].flag=tree[rs].flag=0;
if(tree[rt].sum==0)
{
tree[ls].sum=tree[ls].olm=tree[ls].orm=tree[ls].omm=0;
tree[rs].sum=tree[rs].olm=tree[rs].orm=tree[rs].omm=0;
tree[ls].zlm=tree[ls].zrm=tree[ls].zmm=tree[ls].len();
tree[rs].zlm=tree[rs].zrm=tree[rs].zmm=tree[rs].len();
}
else
{
tree[ls].sum=tree[ls].olm=tree[ls].orm=tree[ls].omm=tree[ls].len();
tree[rs].sum=tree[rs].olm=tree[rs].orm=tree[rs].omm=tree[rs].len();
tree[ls].zlm=tree[ls].zrm=tree[ls].zmm=0;
tree[rs].zlm=tree[rs].zrm=tree[rs].zmm=0;
}
}
if(tree[rt].flag)
{
int ls=rt<<1,rs=rt<<1|1;
swap(tree[ls].olm,tree[ls].zlm);
swap(tree[ls].orm,tree[ls].zrm);
swap(tree[ls].omm,tree[ls].zmm);
swap(tree[rs].olm,tree[rs].zlm);
swap(tree[rs].orm,tree[rs].zrm);
swap(tree[rs].omm,tree[rs].zmm);
tree[rs].sum=tree[rs].len()-tree[rs].sum;
tree[ls].sum=tree[ls].len()-tree[ls].sum;
if(tree[ls].sum==tree[ls].len()||tree[ls].sum==0)
tree[ls].flag=0;
else tree[ls].flag^=1;
if(tree[rs].sum==tree[rs].len()||tree[rs].sum==0)
tree[rs].flag=0;
else tree[rs].flag^=1;
tree[rt].flag=0;
}
}
void build(int rt,int l,int r)
{
tree[rt].l=l,tree[rt].r=r;
tree[rt].flag=0;
if(l==r)
{
tree[rt].sum=tree[rt].olm=tree[rt].orm=tree[rt].omm=array[l];
tree[rt].zlm=tree[rt].zrm=tree[rt].zmm=1-array[l];
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushUp(&tree[rt],&tree[rt<<1],&tree[rt<<1|1]);
}
void update(int rt,int l,int r,int op)
{
if(tree[rt].l>=l&&tree[rt].r<=r)
{
if(op==0)
{
tree[rt].flag=0;
tree[rt].sum=tree[rt].olm=tree[rt].orm=tree[rt].omm=0;
tree[rt].zlm=tree[rt].zrm=tree[rt].zmm=tree[rt].len();
}
else if(op==1)
{
tree[rt].flag=0;
tree[rt].sum=tree[rt].olm=tree[rt].orm=tree[rt].omm=tree[rt].len();
tree[rt].zlm=tree[rt].zrm=tree[rt].zmm=0;
}
else if(op==2)
{
swap(tree[rt].olm,tree[rt].zlm);
swap(tree[rt].orm,tree[rt].zrm);
swap(tree[rt].omm,tree[rt].zmm);
tree[rt].sum=tree[rt].len()-tree[rt].sum;
if(tree[rt].sum==tree[rt].len()||tree[rt].sum==0)
tree[rt].flag=0;
else
tree[rt].flag^=1;
}
return ;
}
if(tree[rt].l==tree[rt].r) return ;
pushDown(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
if(l<=mid) update(rt<<1,l,r,op);
if(r>mid) update(rt<<1|1,l,r,op);
pushUp(&tree[rt],&tree[rt<<1],&tree[rt<<1|1]);
}
int Sum(int rt,int l,int r)//求区间1的个数
{
if(tree[rt].l>=l&&tree[rt].r<=r)
return tree[rt].sum;
if(tree[rt].l==tree[rt].r) return tree[rt].sum;
pushDown(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
int res=0;
if(l<=mid) res+=Sum(rt<<1,l,r);
if(r>mid) res+=Sum(rt<<1|1,l,r);
pushUp(&tree[rt],&tree[rt<<1],&tree[rt<<1|1]);
return res;
}
int LCS(int rt,int l,int r)//求区间最长连续1的个数
{
if(tree[rt].l==l&&tree[rt].r==r)
return tree[rt].omm;
pushDown(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
int ans=0;
if(r<=mid) ans=LCS(rt<<1,l,r);
else if(l>mid) ans=LCS(rt<<1|1,l,r);
else
{
int ls=LCS(rt<<1,l,mid);
int rs=LCS(rt<<1|1,mid+1,r);
ans=max(ls,rs);
ans=max(ans,min(mid-l+1,tree[rt<<1].orm)+min(r-mid,tree[rt<<1|1].olm));
}
pushUp(&tree[rt],&tree[rt<<1],&tree[rt<<1|1]);
return ans;
}
int main()
{
int T;
int n,m,op;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
scanf("%d",array+i);
build(1,0,n-1);
// printf("sum=%d\n",Sum(1,0,n-1));
// printf("LCS=%d\n",LCS(1,0,n-1).omm);
while(m--)
{
int a,b;
scanf("%d%d%d",&op,&a,&b);
if(op<3)
{
update(1,a,b,op);
// printf("sum=%d\n",Sum(1,0,n-1));
// printf("LCS=%d\n",LCS(1,0,n-1).omm);
}
else if(op==3)
{
printf("%d\n",Sum(1,a,b));
// printf("sum=%d\n",Sum(1,0,n-1));
// printf("LCS=%d\n",LCS(1,0,n-1).omm);
}
else
{
printf("%d\n",LCS(1,a,b));
// printf("sum=%d\n",Sum(1,0,n-1));
// printf("LCS=%d\n",LCS(1,0,n-1).omm);
}
}
}
return 0;
}