Black And White
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4401 Accepted Submission(s): 1280
Problem Description
There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she want to know the longest period of consecutive black stones in a range [i, j].
Input
There are multiple cases, the first line of each case is an integer n(1<= n <= 10^5), followed by n integer 1 or 0(1 indicates black stone and 0 indicates white stone), then is an integer M(1<=M<=10^5) followed by M operations formatted as x i j(x = 0 or 1) , x=1 means change the color of stones in range[i,j], and x=0 means ask the longest period of consecutive black stones in range[i,j]
Output
When x=0 output a number means the longest length of black stones in range [i,j].
Sample Input
4 1 0 1 0 5 0 1 4 1 2 3 0 1 4 1 3 3 0 4 4
Sample Output
1 2 0
恩,题目大意就是说,一排石头只有黑色和白色,然后小羊的画笔可以将连续的黑色石头变为白色,白色石头变为黑色,然后 1 i j 表示改变从 i 到 j 区间内石头的颜色,0 i j 表示询问从 i 到 j 最长的连续的黑色石头的长度
//ls1表示从左边数连续的1的个数 rs1从右边数 ms1总的
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100000+10
using namespace std;
struct lnode
{
int l,r,len;
int ls1,ls0,rs1,rs0,ms0,ms1;
int mark;
}node[maxn<<2];
int rec[maxn];
void pushup(int o)
{
node[o].ls1=node[o<<1].ls1;//首先从左边数连续1的个数等于左子树从左边数
if(node[o<<1].ls1==node[o<<1].len)//若它等于左子树的长度则可以加上右子树从左边数的
node[o].ls1+=node[o<<1|1].ls1;
node[o].rs1=node[o<<1|1].rs1;
if(node[o<<1|1].rs1==node[o<<1|1].len)
node[o].rs1+=node[o<<1].rs1;
node[o].ms1=max(max(node[o<<1].ms1,node[o<<1|1].ms1),(node[o<<1].rs1+node[o<<1|1].ls1));//这里比较左子树和右子树以及两子树中间的
node[o].ls0=node[o<<1].ls0;
if(node[o<<1].ls0==node[o<<1].len)
node[o].ls0+=node[o<<1|1].ls0;
node[o].rs0=node[o<<1|1].rs0;
if(node[o<<1|1].rs0==node[o<<1|1].len)
node[o].rs0+=node[o<<1].rs0;
node[o].ms0=max(max(node[o<<1].ms0,node[o<<1|1].ms0),(node[o<<1].rs0+node[o<<1|1].ls0));
}
void pushdown(int o)
{
if(node[o].mark==1)
{
node[o<<1].mark^=1;//至于这里的异或现在还不太懂。。。。
node[o<<1|1].mark^=1;
node[o].mark=0;
swap(node[o<<1].ls1,node[o<<1].ls0);//直接将1变为0了
swap(node[o<<1].rs1,node[o<<1].rs0);
swap(node[o<<1].ms1,node[o<<1].ms0);
swap(node[o<<1|1].ls1,node[o<<1|1].ls0);
swap(node[o<<1|1].rs1,node[o<<1|1].rs0);
swap(node[o<<1|1].ms1,node[o<<1|1].ms0);
}
}
void build(int o,int l,int r)
{
node[o].l=l;
node[o].r=r;
node[o].len=r-l+1;
node[o].mark=0;
if(l==r)
{
node[o].ls1=node[o].rs1=node[o].ms1=rec[l]?1:0;
node[o].ls0=node[o].rs0=node[o].ms0=rec[l]?0:1;
return ;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
pushup(o);
}
void update(int o,int l,int r)
{
if(node[o].l==l&&node[o].r==r)
{
node[o].mark^=1;
swap(node[o].ls1,node[o].ls0);
swap(node[o].rs1,node[o].rs0);
swap(node[o].ms1,node[o].ms0);
return ;
}
pushdown(o);
int mid=(node[o].l+node[o].r)>>1;
if(r<=mid)
update(o<<1,l,r);
else if(l>mid)
update(o<<1|1,l,r);
else
{
update(o<<1,l,mid);
update(o<<1|1,mid+1,r);
}
pushup(o);
}
int query(int o,int l,int r)
{
if(node[o].l==l&&node[o].r==r)
return node[o].ms1;
pushdown(o);
int mid=(node[o].l+node[o].r)>>1;
if(r<=mid)
return query(o<<1,l,r);
else if(l>mid)
return query(o<<1|1,l,r);
else
{
int ls=query(o<<1,l,mid);
int rs=query(o<<1|1,mid+1,r);
int aa=node[o<<1].rs1;
if(aa>mid-l+1)//左子树的最长的1不可能分布在从mid到 l 的左边,最长到 l
aa=mid-l+1;
int bb=node[o<<1|1].ls1;
if(bb>r-mid)//这里因为像上面一样加了1让我找错找了好久。。。因为右子树不包括mid所以不能加1
bb=r-mid;
return max(max(ls,rs),(aa+bb));//aa+bb 为中间的
}
}
int main()
{
int n,m,x,a,b;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;++i)
scanf("%d",&rec[i]);
build(1,1,n);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&x,&a,&b);
if(x==0)
printf("%d\n",query(1,a,b));
else if(x==1)
update(1,a,b);
}
}
return 0;
}