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

Posted kls123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3911 Black And White (线段树 区间合并)相关的知识,希望对你有一定的参考价值。

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911

题意:

给你一段01序列,有两个操作:

1.区间异或,2.询问区间最长的连续的1得长度

思路:

线段树区间合并,开六个数组分别表示:

lsum0   区间左边界开始从左到右连续0的个数

rsum0   区间右边界开始从右到左连续0的个数

lsum1  rsum1 根据上面的可以看出

sum0  区间最长的连续0的个数

sum1 区间最长的连续1的个数

碰到i区间异或操作,我们直接奖这几个数组换下就好了

 

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long
#define ull unsigned long long

const int M = 1e5 + 10;
int lsum1[M<<2],rsum1[M<<2],sum1[M<<2],lsum0[M<<2],rsum0[M<<2],sum0[M<<2],lazy[M<<2];
int a[M];
void pushup(int l,int r,int rt){
    mid;
    lsum1[rt] = lsum1[rt<<1]; lsum0[rt] = lsum0[rt<<1];
    rsum1[rt] = rsum1[rt<<1|1];  rsum0[rt] = rsum0[rt<<1|1];
    if(lsum1[rt] == m-l+1) lsum1[rt] += lsum1[rt<<1|1];
    if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<1];
    if(lsum0[rt] == m-l+1) lsum0[rt] += lsum0[rt<<1|1];
    if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<1];
    sum0[rt] = max(max(sum0[rt<<1],sum0[rt<<1|1]),rsum0[rt<<1]+lsum0[rt<<1|1]);
    sum1[rt] = max(max(sum1[rt<<1],sum1[rt<<1|1]),rsum1[rt<<1]+lsum1[rt<<1|1]);
}

void swa(int rt){
   swap(lsum0[rt],lsum1[rt]);
   swap(rsum0[rt],rsum1[rt]);
   swap(sum0[rt],sum1[rt]);
}

void pushdown(int l,int r,int rt){
    if(lazy[rt]){
        lazy[rt<<1] ^= lazy[rt];
        lazy[rt<<1|1] ^= lazy[rt];
        swa(rt<<1); swa(rt<<1|1);
        lazy[rt] = 0;
    }
}

void build(int l,int r,int rt){
    lazy[rt] = 0;
    lsum1[rt] = rsum1[rt] = sum1[rt] = 0;
    lsum0[rt] = rsum0[rt] = sum0[rt] = 0;
    if(l == r){
        if(a[l]){
            lsum1[rt] = rsum1[rt] = sum1[rt] = 1;
            lsum0[rt] = rsum0[rt] = sum0[rt] = 0;
        }
        else{
            lsum1[rt] = rsum1[rt] = sum1[rt] = 0;
            lsum0[rt] = rsum0[rt] = sum0[rt] = 1;
        }
        return ;
    }
    mid;
    build(lson);  build(rson);
    pushup(l,r,rt);
}


void update(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        lazy[rt] ^= 1;
        swa(rt);
        return ;
    }
    pushdown(l,r,rt);
    mid;
    if(L <= m) update(L,R,lson);
    if(R > m) update(L,R,rson);
    pushup(l,r,rt);
}

int query(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return sum1[rt];
    }
    pushdown(l,r,rt);
    mid;
    if(L > m) return query(L,R,rson);
    if(R <= m) return query(L,R,lson);
    int t1 = query(L,R,lson);
    int t2 = query(L,R,rson);
    int rs = min(lsum1[rt<<1|1],R-m);
    int ls = min(m-L+1,rsum1[rt<<1]);
    return max(max(t1,t2),ls+rs);
}

int main()
{
    int n,op,x,y,q;
    while(scanf("%d",&n)!=EOF){
    for(int i = 1;i <= n;i ++){
        scanf("%d",&a[i]);
    }
    build(1,n,1);
    scanf("%d",&q);
   while(q--){
        scanf("%d%d%d",&op,&x,&y);
        if(op == 1)   update(x,y,1,n,1);
        else printf("%d
",query(x,y,1,n,1));
    }
    }
    return 0;
}

 

以上是关于hdu 3911 Black And White (线段树 区间合并)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3911 Black and White (线段树,区间翻转)

[HDOJ3911]Black And White(线段树,区间合并)

HDU 5113--Black And White(搜索+剪枝)

HDU 5113 Black And White

搜索(剪枝优化):HDU 5113 Black And White

hdu-5583 Kingdom of Black and White(数学,贪心,暴力)