题意:给一行棋子(只有黑色和白色,1为黑,0为白),长度为100000。有m个操作,x,l,r 若x==0,查询(l,r)区间内连续的黑棋最大数量,若x==1,翻转(l,r)区间。
#include <iostream>
#include<stdio.h>
using namespace std;
#define maxn 500001
int n,m,a[maxn];
int max(int x,int y,int z)
{
return max(max(x,y),z);
}
void swap(int *ji1,int *ji2)
{
int t;
t=*ji1;
*ji1=*ji2;
*ji2=t;
}
struct node
{
int l,r,ll1,rr1,m1,ll0,rr0,m0,c;
}tr[maxn*4];
void pushup(int id)
{
int len1,len2;
len1=tr[id*2].r-tr[id*2].l+1;
len2=tr[id*2+1].r-tr[id*2+1].l+1;
tr[id].ll1=tr[id*2].ll1;
tr[id].rr1=tr[id*2+1].rr1;
if(tr[id*2].ll1==len1)tr[id].ll1+=tr[id*2+1].ll1;
if(tr[id*2+1].rr1==len2)tr[id].rr1+=tr[id*2].rr1;
tr[id].m1=max(tr[id*2].m1,tr[id*2+1].m1,tr[id*2].rr1+tr[id*2+1].ll1);//在id节点 只考虑ll1,rr1但是有可能中间段是最大的
tr[id].ll0=tr[id*2].ll0;
tr[id].rr0=tr[id*2+1].rr0;
if(tr[id*2].ll0==len1)tr[id].ll0+=tr[id*2+1].ll0;
if(tr[id*2+1].rr0==len2)tr[id].rr0+=tr[id*2].rr0;
tr[id].m0=max(tr[id*2].m0,tr[id*2+1].m0,tr[id*2].rr0+tr[id*2+1].ll0);
}
void bulid(int id,int l,int r)
{
tr[id].l=l;
tr[id].r=r;
tr[id].c=0;
if(l==r)
{
tr[id].ll1=tr[id].m1=tr[id].rr1=a[l]?1:0;
tr[id].ll0=tr[id].m0=tr[id].rr0=a[l]?0:1;
}
else
{
int mid=(l+r)/2;
bulid(id*2,l,mid);
bulid(id*2+1,mid+1,r);
pushup(id);
}
}
void exchang(int id)
{
if(tr[id].c==1)
tr[id].c=0;
else tr[id].c=1;//此处注意,重复更新同样的区间,则相当于没更新
swap(tr[id].ll0,tr[id].ll1);
swap(tr[id].rr0,tr[id].rr1);
swap(tr[id].m0,tr[id].m1);
}
void pushdown(int id)
{
exchang(id*2);
exchang(id*2+1);
tr[id].c=0;
}
int query(int id,int l,int r)
{
if(l<=tr[id].l&&tr[id].r<=r)
{
return tr[id].m1;
}
else
{
if(tr[id].c!=0)
{
pushdown(id);
}
int mid=(tr[id].r+tr[id].l)/2;
if(r<=mid)return query(id*2,l,r);
else if(l>mid)return query(id*2+1,l,r);
//*************************//
else
{
int l1=query(id*2,l,r);
int r1=query(id*2+1,l,r);
int a=tr[id*2].rr1;//左子树右边最长连续1,注意它的个数不应该大于区间[l,tr[rt<<1].r]的个数
int b=tr[id*2+1].ll1;//右子树左边最长连续1,注意它的个数不应该大于区间[tr[rt<<1|1].l,r]的个数
if(a>tr[id*2].r-l+1)a=tr[id*2].r-l+1;
if(b>r-tr[id*2+1].l+1)b=r-tr[id*2+1].l+1;
return max(l1,r1,a+b);
}
//*************************//
}
}
void update(int id,int l,int r)
{
if(l<=tr[id].l&&tr[id].r<=r)
{
exchang(id);//此处注意,重复更新同样的区间,则相当于没更新
}
else
{
if(tr[id].c!=0)
pushdown(id);
int mid=(tr[id].r+tr[id].l)/2;
if(r<=mid)update(id*2,l,r);
else if(l>mid)update(id*2+1,l,r);
else
{
update(id*2,l,r);
update(id*2+1,l,r);
}
pushup(id);
}
}
int main()
{
int i,l,r,t;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
bulid(1,1,n);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&t,&l,&r);
if(t==0)
{
printf("%d\n",query(1,l,r));
}
else
{
update(1,l,r);
}
}
}
return 0;
}