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; }