Black And White(线段树+区间合并)

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;
}
发布了33 篇原创文章 · 获赞 15 · 访问量 917

猜你喜欢

转载自blog.csdn.net/weixin_43925900/article/details/97411553