【线段树_区间合并_异或翻转】HDU 3911 Black And White

 HDU 3911 Black And White

  • 题意:有一个只有0和1组成的序列。对这个序列有两个操作:(1)对区间进行翻转。也就是0变1,1变0.  (2)查询区间连续1的序列的最大长度

区间合并(一定要注意左右子区间合并后的连续序列

结构体元素:

  1. oneL:区间左端点开始向右连续1的个数
  2. oneR:区间右端点开始向左连续1的个数
  3. onemx:区间最大的连续1的个数

如何合并?

  1. rt区间的oneL是等于左儿子区间的oneL,但是当左儿子区间全是1,那么rt区间的oneL就可以延伸到右儿子的oneL
  2. rt区间的oneR与oneL相同
  3. rt区间的最大连续1的个数必然是左右儿子最大连续1的个数以及左儿子oneR+右儿子oneL三者中的最大值
tree[rt].oneL = tree[lsn].oneL;
if(tree[lsn].oneR == mid - l + 1) tree[rt].oneL += tree[rsn].oneL;
tree[rt].oneR = tree[rsn].oneR;
if(tree[rsn].oneL == r - mid) tree[rt].oneR += tree[lsn].oneR;
tree[rt].onemx = max(tree[lsn].oneR + tree[rsn].oneL, max(tree[lsn].onemx, tree[rsn].onemx));

异或翻转 

要实现翻转,并且还要记录连续1的最大长度,那么我们需要将连续0的信息和1一样记录下来。这样的话,翻转的时候我们只需要交换1和0的信息即可。

那么如何翻转呢?那当然是用懒标记异或1的方式。相同为0不同为1. 如果两次翻转,那就相当于没翻转,非常的奈斯。

需要注意的就是查询的时候。当ql和qr分在两个子区间的时候,我们不能是返回两者之和,而是左右两个子区间以及两个子区间中间可能可以合并的序列中的最大值。【写的时候我就是这里错了……】

return max(min(mid - ql + 1, tree[lsn].oneR) +  min(qr - mid, tree[rsn].oneL), max( query(QL),query(QR)));
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)

#define MID (l + r ) >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid + 1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define eps  1e-6

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 5;
inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
int n, m;
int arr[maxN];
struct node{
    int oneL, oneR, onemx;
    int zeroL, zeroR, zeromx;
    node(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0, int f = 0): oneL(a), oneR(b), onemx(c),zeroL(d), zeroR(e), zeromx(f) {}
}tree[maxN << 2];
int lazy[maxN << 2];
void pushup(int rt, int l, int r)
{
    int mid = MID;
    tree[rt].oneL = tree[lsn].oneL;
    if(tree[lsn].oneR == mid - l + 1) tree[rt].oneL += tree[rsn].oneL;
    tree[rt].oneR = tree[rsn].oneR;
    if(tree[rsn].oneL == r - mid) tree[rt].oneR += tree[lsn].oneR;
    tree[rt].onemx = max(tree[lsn].oneR + tree[rsn].oneL, max(tree[lsn].onemx, tree[rsn].onemx));

    tree[rt].zeroL = tree[lsn].zeroL;
    if(tree[lsn].zeroR == mid - l + 1) tree[rt].zeroL += tree[rsn].zeroL;
    tree[rt].zeroR = tree[rsn].zeroR;
    if(tree[rsn].zeroL == r - mid) tree[rt].zeroR += tree[lsn].zeroR;
    tree[rt].zeromx = max(tree[lsn].zeroR + tree[rsn].zeroL, max(tree[lsn].zeromx, tree[rsn].zeromx));
}
void build_tree(int rt, int l, int r)
{
    if(l == r)
    {
        if(arr[l])
            tree[rt] = node(1, 1, 1, 0, 0, 0);
        else
            tree[rt] = node(0, 0, 0, 1, 1, 1);
        return ;
    }
    int mid = MID;
    build_tree(Lson);
    build_tree(Rson);
    pushup(rt, l, r);
}
void pushdown(int rt)
{
    if(lazy[rt])
    {
        swap(tree[lsn].oneL, tree[lsn].zeroL);
        swap(tree[lsn].oneR, tree[lsn].zeroR);
        swap(tree[lsn].onemx, tree[lsn].zeromx);
        lazy[lsn] ^= lazy[rt];
        swap(tree[rsn].oneL, tree[rsn].zeroL);
        swap(tree[rsn].oneR, tree[rsn].zeroR);
        swap(tree[rsn].onemx, tree[rsn].zeromx);
        lazy[rsn] ^= lazy[rt];
        lazy[rt] = 0;
    }
}
void update(int rt, int l, int r, int ql, int qr)//翻转
{
    if(ql <= l && qr >= r)
    {
        swap(tree[rt].oneL, tree[rt].zeroL);
        swap(tree[rt].oneR, tree[rt].zeroR);
        swap(tree[rt].onemx, tree[rt].zeromx);
        lazy[rt] ^= 1;
        return;
    }
    pushdown(rt);
    int mid = MID;
    if(qr <= mid) update(QL);
    else if(ql > mid) update(QR);
    else { update(QL); update(QR); }
    pushup(rt, l, r);
}
int query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && qr >= r)
        return tree[rt].onemx;
    pushdown(rt);
    int mid = MID;
    if(qr <= mid) return query(QL);
    else if(ql > mid) return query(QR);
    else return max(min(mid - ql + 1, tree[lsn].oneR) +  min(qr - mid, tree[rsn].oneL), max( query(QL),query(QR)));
}
void init()
{
    memset(lazy, 0, sizeof(lazy));
}
int main()
{
    while(~scanf("%d", &n))
    {
        init();
        for(int i = 1; i <= n; i ++ ) arr[i] = read();
        build_tree(1, 1, n);
        m = read();
        while(m -- )
        {
            int op, l, r; op = read(); l = read(); r = read();
            if(op)//change color
                update(1, 1, n, l, r);
            else//查询
                printf("%d\n", query(1, 1, n, l, r));
        }
    }
    return 0;
}
/*
10
1 1 1 1 1 1 1 1 1 1
100
1 7 7
0 6 8
1 5 7
0 1 5
0 5 7
0 4 7
 */
发布了190 篇原创文章 · 获赞 57 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104012836