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
题目大概就是说输入0就是查询区间内的1的和,输入1,就把区间内的值异或一遍,那么我选择线段树
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=100010;
int n,m,sum1[maxn*5],lsum1[maxn*5],rsum1[maxn*5],cover[maxn*5],sum2[maxn*5],lsum2[maxn*5],rsum2[maxn*5];
//lsum1表示当前节点从左往右的最大连续的1的个数,lsum2表示当前节点从左往右的最大连续的0的个数,其他的sum同理
//记录最大连续的1和0的个数,那么在修改的时候直接交换就行了
//cover是lazy标签
inline int Max(int a,int b)//据说这样会快一点
{
return a>b?a:b;
}
inline int Min(int a,int b)
{
return a<b?a:b;
}
void sovle(int rt)
{
swap(lsum1[rt],lsum2[rt]);
swap(rsum1[rt],rsum2[rt]);
swap(sum1[rt],sum2[rt]);
}
void pushup(int rt,int m)
{
lsum1[rt]=lsum1[rt<<1];
lsum2[rt]=lsum2[rt<<1];
if(lsum1[rt<<1]==m-(m>>1))lsum1[rt]+=lsum1[rt<<1|1];
if(lsum2[rt<<1]==m-(m>>1))lsum2[rt]+=lsum2[rt<<1|1];//左区间的最大值
rsum1[rt]=rsum1[rt<<1|1];
rsum2[rt]=rsum2[rt<<1|1];
if(rsum1[rt<<1|1]==(m>>1))rsum1[rt]+=rsum1[rt<<1];
if(rsum2[rt<<1|1]==(m>>1))rsum2[rt]+=rsum2[rt<<1];//右区间的
sum1[rt]=Max(rsum1[rt<<1]+lsum1[rt<<1|1],Max(sum1[rt<<1],sum1[rt<<1|1]));
sum2[rt]=Max(rsum2[rt<<1]+lsum2[rt<<1|1],Max(sum2[rt<<1],sum2[rt<<1|1]));//中间向两边的
}
void pushdown(int rt)
{
if(cover[rt])
{
cover[rt<<1]^=1,cover[rt<<1|1]^=1;
cover[rt]=0;
sovle(rt<<1),sovle(rt<<1|1);
}
}
void build(int l,int r,int rt)//边读边建树,简直6666
{
cover[rt]=0;
if(l==r)
{
int j;
scanf("%d",&j);
lsum1[rt]=rsum1[rt]=sum1[rt]=j;//简便写法.
lsum2[rt]=rsum2[rt]=sum2[rt]=!j;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt,r-l+1);
}
void updata(int x,int y,int l,int r,int rt)
{
if(l>=x&&r<=y)
{
cover[rt]^=1;
sovle(rt);
return;
}
pushdown(rt);
int m=(l+r)>>1;
if(x<=m)updata(x,y,lson);
if(y>m)updata(x,y,rson);
pushup(rt,r-l+1);
}
int query(int x,int y,int l,int r,int rt)
{
if(l>=x&&r<=y)return sum1[rt];
pushdown(rt);
int m=(l+r)>>1;
if(x>m)return query(x,y,rson);
if(y<=m)return query(x,y,lson);
return Max(Min(m-x+1,rsum1[rt<<1])+Min(y-m,lsum1[rt<<1|1]),Max(query(x,y,lson),query(x,y,rson)));//左右和中间的最大值
}
int main()
{
int op,a,b;
while(~scanf("%d",&n))
{
build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&op,&a,&b);
if(op)updata(a,b,1,n,1);
else printf("%d\n",query(a,b,1,n,1));
}
}
return 0;
}