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
题目链接 : HDU 3911
这道题目就是叫我们求一个区间最大连续的1的数量,简单用线段树维护一下就行。
用大佬们的话来说就是:*****签到题
可我就是不会,嘤嘤嘤QWQ
题目思路:
区间维护思路:
很明显的维护区间,但是要怎么维护是个问题。
我们可以从题目中很明显的得到,如果一个区间***作次数为偶数就不用管,对吧。
所以我们可以用一个变量来表示当前是偶数次还是奇数次。(就每次异或1嘛,自己想想是不是。)
然后我们再看一下,我们需要的信息,也就是答案,最大连续1的和,怎么去维护。
比如当前我们到了某一个区间,我们想一下,这个区间怎么由两个子区间得到呢?
这个时候有三种情况:
- 答案是左区间的最大连续1的和
- 答案是右区间的最大连续1的和
- 答案是左区间的最大连续靠右1的和 + 答案是右区间的最大连续靠左的1的和
由上面的三种情况我们可以想到,去维护 最大连续靠右1的和 与 最大连续靠左的1的和 , 这样我们就可以很简单的得到我们想要的答案了。
区间修改维护思路:
虽然我们可以判断奇偶来剪枝,但是我们还是需要真实地去维护这个区间。
怎么维护呢?
刚刚我们记录了关于所有1的信息,如果我们再把0的信息记录一下,当区间需要修改时,交换这两种信息不就可以了吗?
答案查询思路:
怎么去从一个区间查询我们要的信息呢?
这个时候我们要考虑两种情况:
- 答案是一个完整的区间
- 答案是由两个不完整的区间组合而成
如果答案是完整的区间,我们直接返回这个区间的信息就可以了。
如果答案不是完整区间呢?
这个时候我们想到,上面我们已经记录了,最大连续靠右1的和 与 最大连续靠左的1的和这么重要的信息,同理,我们组合起来求一个最大值不就可以了吗?
但是我们要注意一个问题,比如:
左区间靠右连续1 的和,可能大于我们要查找的这个区间长度,那么我们答案就错了,这个时候,我们需要取个min就可以了。
**最重要的一点:**这道题是多组输入,没多组WA了一次(QAQ)
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
struct node{
int l,r,ls,rs,s,col,lazy,ls1,rs1,s1;
}t[N<<2];
void push_up(int p){
t[p].s=max(t[p<<1].s,max(t[p<<1|1].s,t[p<<1].rs+t[p<<1|1].ls));
if(t[p<<1].s==t[p<<1].r-t[p<<1].l+1) t[p].ls=t[p<<1].s+t[p<<1|1].ls;
if(t[p<<1|1].s==t[p<<1|1].r-t[p<<1|1].l+1) t[p].rs=t[p<<1|1].s+t[p<<1].rs;
else t[p].rs=t[p<<1|1].rs;
t[p].s1=max(t[p<<1].s1,max(t[p<<1|1].s1,t[p<<1].rs1+t[p<<1|1].ls1));
if(t[p<<1].s1==t[p<<1].r-t[p<<1].l+1) t[p].ls1=t[p<<1].s1+t[p<<1|1].ls1;
else t[p].ls1=t[p<<1].ls1;
if(t[p<<1|1].s1==t[p<<1|1].r-t[p<<1|1].l+1) t[p].rs1=t[p<<1|1].s1+t[p<<1].rs1;
else t[p].rs1=t[p<<1|1].rs1;
}
void push_down(int p){
if(t[p].lazy){
swap(t[p<<1].s,t[p<<1].s1); swap(t[p<<1].ls,t[p<<1].ls1);
swap(t[p<<1].rs,t[p<<1].rs1); swap(t[p<<1|1].s,t[p<<1|1].s1);
swap(t[p<<1|1].rs,t[p<<1|1].rs1); swap(t[p<<1|1].ls,t[p<<1|1].ls1);
t[p<<1].lazy^=1; t[p<<1|1].lazy^=1;
t[p].lazy=0;
}
}
void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r){
scanf("%d",&t[p].col);
if(t[p].col) t[p].s=t[p].ls=t[p].rs=1;
else t[p].s1=t[p].ls1=t[p].rs1=1;
return ;
}
int mid=l+r>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
push_up(p);
}
void change(int p,int l,int r){
if(t[p].l==l&&t[p].r==r){
swap(t[p].s,t[p].s1); swap(t[p].ls,t[p].ls1); swap(t[p].rs,t[p].rs1);
t[p].lazy^=1; return ;
}
push_down(p);
int mid=t[p].l+t[p].r>>1;
if(r<=mid) change(p<<1,l,r);
else if(l>mid) change(p<<1|1,l,r);
else change(p<<1,l,mid),change(p<<1|1,mid+1,r);
push_up(p);
}
int ask(int p,int l,int r){
if(t[p].l==l&&t[p].r==r) return t[p].s;
int mid=t[p].l+t[p].r>>1;
push_down(p);
if(r<=mid) return ask(p<<1,l,r);
else if(l>mid) return ask(p<<1|1,l,r);
else{
int flag=min(mid-l+1,t[p<<1].rs)+min(r-mid,t[p<<1|1].ls);
return max(flag,max(ask(p<<1,l,mid),ask(p<<1|1,mid+1,r)));
}
}
int main(){
while(~scanf("%d",&n)){
memset(t,0,sizeof t);
build(1,1,n);
scanf("%d",&m);
while(m--){
int x,i,j; scanf("%d %d %d",&x,&i,&j);
if(x) change(1,i,j);
else printf("%d\n",ask(1,i,j));
}
}
return 0;
}