Black And White
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构成的数字,每次可以指定一个区间中的0变成1,1变成0,求若干次操作后,给定区间内的最长连续1的长度。
解题思路:线段树。在这颗线段树中,我们要储存的有6个变量,分别是:
struct node
{
int l0len,l1len,r0len,r1len,max1len,max0len;
int len;
int lazy;
}qwe[maxn<<2];
从左向右的连续1长度、从右向左的连续1长度,该区间中最长1长度。同样,从左向右连续0长度、从右向左连续0长度、该区间中最长0长度。
假设有一串序列1 0 1 1 0
,我们要求[1,5]这个区间的最长1长度。由线段树的原理,我们可以由[1,3]和[4,5]这两个区间得到。很多同学可能会说maxlen[1,5]=max ([1,3],[4,5])。但其实不是这样的,因为有可能这两个区间的链接部分,也有可能构成连续的1序列。因此,有如下代码。
tmp=qwe[root<<1].r1len+qwe[root<<1|1].l1len;
qwe[root].max1len=max(max(qwe[root<<1].max1len,qwe[root<<1|1].max1len),tmp);
怎更改和查询一个区间呢?和其他的线段树不同,这道题并不严格要求l==ql&&r==qr
,只要求l>=cl&&r<=cr
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define ll long long
#define lowbit(x) (x&(-x))
#define MT(a,b) memset(a,b,sizeof(a))
const int maxn=1E5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
int num[maxn];
struct node
{
int l0len,l1len,r0len,r1len,max1len,max0len;
int len;
int lazy;
}qwe[maxn<<2];
void update(int root)
{
int tmp;
qwe[root].len=qwe[root<<1].len+qwe[root<<1|1].len;
qwe[root].l0len=qwe[root<<1].l0len;
if (qwe[root<<1].l0len==qwe[root<<1].len) qwe[root].l0len+=qwe[root<<1|1].l0len;
qwe[root].l1len=qwe[root<<1].l1len;
if (qwe[root<<1].l1len==qwe[root<<1].len) qwe[root].l1len+=qwe[root<<1|1].l1len;
qwe[root].r0len=qwe[root<<1|1].r0len;
if (qwe[root<<1|1].r0len==qwe[root<<1|1].len) qwe[root].r0len+=qwe[root<<1].r0len;
qwe[root].r1len=qwe[root<<1|1].r1len;
if (qwe[root<<1|1].r1len==qwe[root<<1|1].len) qwe[root].r1len+=qwe[root<<1].r1len;
tmp=qwe[root<<1].r0len+qwe[root<<1|1].l0len;
qwe[root].max0len=max(max(qwe[root<<1].max0len,qwe[root<<1|1].max0len),tmp);
tmp=qwe[root<<1].r1len+qwe[root<<1|1].l1len;
qwe[root].max1len=max(max(qwe[root<<1].max1len,qwe[root<<1|1].max1len),tmp);
}
void build_tree(int l,int r,int root)
{
qwe[root].lazy=0;
if (l==r){
qwe[root].max1len=num[l];
qwe[root].l1len=num[l];
qwe[root].r1len=num[l];
qwe[root].max0len=1-num[l];
qwe[root].l0len=1-num[l];
qwe[root].r0len=1-num[l];
qwe[root].len=1;
return;
}
int mid=(l+r)>>1;
build_tree(l,mid,root<<1);
build_tree(mid+1,r,root<<1|1);
update(root);
// printf ("%d %dto%d len=%d %d %d\n",root,l,r,qwe[root].len,qwe[root].l1len,qwe[root].r1len);
}
void pushdown(int root)
{
if (qwe[root].lazy){
qwe[root<<1].lazy^=1;
qwe[root<<1|1].lazy^=1;
swap(qwe[root<<1].l1len,qwe[root<<1].l0len);
swap(qwe[root<<1].r1len,qwe[root<<1].r0len);
swap(qwe[root<<1].max0len,qwe[root<<1].max1len);
swap(qwe[root<<1|1].l1len,qwe[root<<1|1].l0len);
swap(qwe[root<<1|1].r1len,qwe[root<<1|1].r0len);
swap(qwe[root<<1|1].max0len,qwe[root<<1|1].max1len);
qwe[root].lazy=0;
}
}
void change (int l,int r,int cl,int cr,int root)
{
if (l>=cl&&r<=cr){
qwe[root].lazy^=1;
swap(qwe[root].l1len,qwe[root].l0len);
swap(qwe[root].r1len,qwe[root].r0len);
swap(qwe[root].max0len,qwe[root].max1len);
return;
}
pushdown(root);
int mid=(l+r)>>1;
if (cl<=mid) change(l,mid,cl,cr,root<<1);
if (cr>=mid+1) change(mid+1,r,cl,cr,root<<1|1);
update(root);
}
int query (int l,int r,int ql,int qr,int root)
{
if (l>=ql&&r<=qr){
return qwe[root].max1len;
}
pushdown(root);
int mid=(l+r)>>1;
if (qr<=mid) return query(l,mid,ql,qr,root<<1);
else if (ql>mid) return query(mid+1,r,ql,qr,root<<1|1);
else {
int a,b,c;
a=query(l,mid,ql,mid,root<<1);
b=query(mid+1,r,mid+1,qr,root<<1|1);
c=min(qwe[root<<1].r1len,mid-ql+1)+min(qwe[root<<1|1].l1len,qr-mid);
return max(max(a,b),c);
}
}
int main ()
{
int a,b,c;
int m,n;while (~scanf ("%d",&n)){
MT(qwe,0);
for (int i=1;i<=n;i++){
scanf ("%d",&num[i]);
}
build_tree(1,n,1);
// for (int i=1;i<=2*n;i++){
// printf ("%d %d %d %d\n",i,qwe[i].r1len,qwe[i].r1len);
// }
scanf ("%d",&m);
for (int i=1;i<=m;i++){
scanf ("%d%d%d",&a,&b,&c);
if (a==0){
printf("%d\n",query(1,n,b,c,1));
} else if (a==1){
change(1,n,b,c,1);
}
}
}
return 0;
}