线段树区间翻转,区间找最长连续数字的长度。

1、题目要求,区间反转,区间找最长连续1长度。

2、首先想到维护以区间左端点开始的最长连续0/1长度,和从区间右端点开始的最长连续1长度,和这个区间的最长连续1长度。

3、反转操作的话,似乎需要重新来算每一个点,对于线段树来说,显然是不可以接受的,所以我们在维护1的时候,顺带维护一下0,当这个区间需要反转的话,实际上就是0变成1,1变成0,那么我们只需要将这个区间的0和1的三个值交换一下就完成了反转操作。

4、所以现在我们的线段树维护以区间左端点开始的最长连续0/1长度,和从区间右端点开始的最长连续0/1长度,和这个区间的最长连续0/1长度。

5、区间合并

先考虑区间合并后的左端点,首先,它等于左边的子区间的左端点最长连续长度,如果他等于左边子区间的长度,那么还需要加上右边子区间的左端点最长连续长度。

右端点同理。

那么最后,区间的最长连续1长度=max(左子区间右端点+右子区间左端点,左子区间左端点,右子区间右端点,左子区间的最长连续长度,右子区间最长连续1长度)

6、在合并的时候,要注意 左子区间右端点+右子区间左端点,这两个值都是处理过后的,需要先判断一下是否大于他们区间的长度,如果大于区间长度,就取区间长度作为他的值。 

题目链接

Code:

#include <bits/stdc++.h>

#define lson left,mid,k<<1

#define rson mid+1,right,k<<1|1

#define imid int mid=(left+right)/2;

using namespace std;

const int MAXN = 1e5 + 5;

struct node

{

    int l;

    int r;

    int mark;//是否需要反转

    int lm1;//左端点开始的最大值 1

    int lm0;

    int rm1;//右端点开始的最大值 1

    int rm0;

    int mm1;//区间最大值

    int mm0;

}que[MAXN * 4];

int ql, qr, val;

int a[MAXN];

int n, m;

void up(int k)

{

    que[k].lm1 = que[k << 1].lm1;

    if (que[k << 1].lm1 == que[k << 1].r - que[k << 1].l + 1)

        que[k].lm1 += que[k << 1 | 1].lm1;

    que[k].rm1 = que[k << 1 | 1].rm1;

    if (que[k << 1 | 1].rm1 == que[k << 1 | 1].r - que[k << 1 | 1].l + 1)

        que[k].rm1 += que[k << 1].rm1;

    que[k].mm1 = que[k << 1].rm1 + que[k << 1 | 1].lm1;

    que[k].mm1 = max(max(que[k << 1].mm1, que[k << 1 | 1].mm1), que[k].mm1);

    que[k].mm1 = max(max(que[k].lm1, que[k].rm1), que[k].mm1);


    que[k].lm0 = que[k << 1].lm0;

    if (que[k << 1].lm0 == que[k << 1].r - que[k << 1].l + 1)

        que[k].lm0 += que[k << 1 | 1].lm0;

    que[k].rm0 = que[k << 1 | 1].rm0;

    if (que[k << 1 | 1].rm0 == que[k << 1 | 1].r - que[k << 1 | 1].l + 1)

        que[k].rm0 += que[k << 1].rm0;

    que[k].mm0 = que[k << 1].rm0 + que[k << 1 | 1].lm0;

    que[k].mm0 = max(max(que[k << 1].mm0, que[k << 1 | 1].mm0), que[k].mm0);

    que[k].mm0 = max(max(que[k].lm0, que[k].rm0), que[k].mm0);

}

void down(int k)

{

    if (que[k].mark)

    {

        que[k << 1].mark ^= 1;

        swap(que[k << 1].lm1, que[k << 1].lm0);

        swap(que[k << 1].rm1, que[k << 1].rm0);

        swap(que[k << 1].mm1, que[k << 1].mm0);

        que[k << 1 | 1].mark ^= 1;

        swap(que[k << 1 | 1].lm1, que[k << 1 | 1].lm0);

        swap(que[k << 1 | 1].rm1, que[k << 1 | 1].rm0);

        swap(que[k << 1 | 1].mm1, que[k << 1 | 1].mm0);

        que[k].mark = 0;

    }

}

void build(int left = 1, int right = n, int k = 1)

{

    que[k].l = left;

    que[k].r = right;

    que[k].mark = 0;

    if (left == right)

    {

        if (a[left] == 1)

        {

            que[k].lm1 = que[k].rm1 = que[k].mm1 = 1;

            que[k].lm0 = que[k].rm0 = que[k].mm0 = 0;

        }

        else

        {

            que[k].lm1 = que[k].rm1 = que[k].mm1 = 0;

            que[k].lm0 = que[k].rm0 = que[k].mm0 = 1;

        }

        return;

    }

    imid;

    build(lson);

    build(rson);

    up(k);

}

void update(int left = 1, int right = n, int k = 1)

{

    if (qr < left || right < ql)

        return;

    if (ql <= left && right <= qr)

    {

        que[k].mark ^= 1;

        swap(que[k].lm1, que[k].lm0);

        swap(que[k].rm1, que[k].rm0);

        swap(que[k].mm1, que[k].mm0);

        return;

    }

    down(k);

    imid;

    update(lson);

    update(rson);

    up(k);

}

int query(int left = 1, int right = n, int k = 1)

{

    if (qr < left || right < ql)

        return 0;

    if (ql <= left && right <= qr)

        return que[k].mm1;

    down(k);

    imid;

    if (qr <= mid) 

        return query(lson);

    else if (ql > mid) 

        return query(rson);

    else

        return max(max(query(lson), query(rson)), min(que[k << 1].rm1, mid - ql + 1) + min(que[k << 1 | 1].lm1, qr - mid));

}

int main()

{

    scanf("%d", &n);

    for (int i = 1; i <= n; i++)

        scanf("%d", &a[i]);

    build();

    scanf("%d", &m);

    int op, q, w;

    while (m--)

    {

        scanf("%d%d%d", &op, &ql, &qr);

        if (op == 0)

        {

            int ans = query();

            printf("%d\n", ans);

        }

        else

        {

            update();

        }

    }

}