本身区间最长连续0之间不可以进行区间加法操作,违背线段树基本的运算。但是容易想到两个区间合并产生的最值变化,主要由Lson的右端连续0长度加上Rson的左端连续0长度引起。即 tree[x].ma=max(tree[Lson].R0+tree[Rson].L0,max(tree[Lson].ma,tree[Rson].ma));
因此我们可以考虑维护一个区间的左端连续0个数和右端连续0个数。
但是在区间合并时我们会发现一个新的问题,即如果左区间全是0,那么tree[x].L0可以向右继续合并,tree[x].R0同理;
tree[x].L0=tree[Lson].L0+(左区间全是0?tree[Rson].L0:0);
tree[x].R0=tree[Rson].R0+(右区间全是0?tree[Rson].R0:0);
查询的时候同样需要注意不能简单返回左右区间的最大值,而是需要考虑左右区间是否存在全为零的情况;
include
using namespace std;
#define INF 0x3f3f3f3f
#define L long long int
#define ls x<<1
#define rs x<<1|1
#define maxn 100005
#define maxm 1000005
int n,m;
int a[maxn];
///---------------------------------------------
///求区间最大连续0的个数 带区间修改和区间查询
struct node{
int l0,r0,ma0;
bool isall0;
node(int l0,int r0,int ma0,bool isall0):l0(l0),r0(r0),ma0(ma0),isall0(isall0){};
node(){};
};
node tree[maxn*4];
bool lazy[maxn];
void pushup(int x)
{
tree[x].l0=tree[ls].l0+(tree[ls].isall0 ? tree[rs].l0 : 0);
tree[x].r0=tree[rs].r0+(tree[rs].isall0 ? tree[ls].r0 : 0);
tree[x].ma0=max(tree[ls].r0+tree[rs].l0,max(tree[ls].ma0,tree[rs].ma0));
tree[x].isall0=tree[ls].isall0&tree[rs].isall0;
}
void pushdown(int x,int l,int r)
{
int mid=(l+r)/2;
tree[ls].l0=tree[ls].r0=tree[ls].ma0=mid-l+1;
tree[rs].l0=tree[rs].r0=tree[rs].ma0=r-mid;
tree[ls].isall0=tree[rs].isall0=1;
lazy[ls]=lazy[rs]=1;
lazy[x]=0;
}
void build(int x,int l,int r)
{
if(l==r){
tree[x].l0=tree[x].r0=tree[x].ma0=tree[x].isall0=a[l]^1;
}
else {
int mid=(l+r)/2;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(x);
}
}
void update(int x,int l,int r,int ll,int rr)
{
if(lazy[x])pushdown(x,l,r);
if(ll<=l&&r<=rr){
tree[x].l0=tree[x].r0=tree[x].ma0=r-l+1;
tree[x].isall0=1;
lazy[x]=1;
return ;
}
else {
int mid=(l+r)/2;
if(mid>=ll)update(ls,l,mid,ll,rr);
if(mid+1<=rr)update(rs,mid+1,r,ll,rr);
pushup(x);
}
}
node query(int x,int l,int r,int ll,int rr)
{
if(lazy[x])pushdown(x,l,r);
if(ll<=l&&r<=rr)return tree[x];
else{
int mid=(l+r)/2;
node now;
now.isall0=now.l0=now.ma0=now.r0=0;
if(rr<=mid)return query(ls,l,mid,ll,rr);
else if(mid+1<=ll)return query(rs,mid+1,r,ll,rr);
else if(ll<=mid&&mid+1<=rr){
node t1=query(ls,l,mid,ll,rr);
node t2=query(rs,mid+1,r,ll,rr);
now.l0=t1.l0+(t1.isall0 ? t2.l0:0);
now.r0=t2.r0+(t2.isall0 ? t1.r0:0);
now.ma0=max(t1.r0+t2.l0,max(t1.ma0,t2.ma0));
now.isall0=t1.isall0&t2.isall0;
return now;
}
}
}
///------------------------------------------------------
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
build(1,1,n);
for(int i=1,x,y,z;i<=m;i++){
scanf("%d",&x);
if(x==1){
scanf("%d%d",&y,&z);
update(1,1,n,y,z);
}
else {
scanf("%d%d",&y,&z);
node ans=query(1,1,n,y,z);
printf("l0 = %d\tr0 = %d\tma0 = %d\n",ans.l0,ans.r0,ans.ma0);
}
}
return 0;
}