HDU 3397 Sequence operation 线段树综合题

题目地址
题意:给你个01串,有以下几种操作。

0.把[l.r]区间的所有数都置为0.
1.把[l.r]区间的所有数都置为1.
2.把[l,r]区间的所有数都置为其相反数.
3.求[l,r]区间内的1的个数.
4.求[l,r]区间内的最长的连续的’1’的个数.

思路:这题我写了一天多了,还是发现是因为急躁好多小细节没有考虑清楚。其实这题适合于刚刚把线段树学完的人来写,因为都是一些基础的操作拼接起来的。题目本身并不难。我来先简要说下我的想法吧。我有两个延时更新标记,一个是覆盖0或者1的标记flag,如果是0操作就把该标记置为0,如果是1操作就把该标记置为1,另一个是判断是否取反的标记x_or(wa一天的点就是2操作是在update的时候忘记把当前标记与1做异或操作,直接给改标记赋1了,导致如果对同一个区间做取反操作2次的结果还是取反)。
操作修改情况:

  1. 如果是覆盖操作的话,无论x_or为多少直接置为0,然后再把flag置为相应的值。
  2. 如果是取反操作的话,先把x_or标记取反,再看如果flag不为-1,并且该x_or标记为1,则flag与1做异或操作,x_or置为0。

输出情况:

  1. 输出1的个数就是最简单的线段树的输出
  2. 输出该区间最长的连续1的序列(这个就是线段树的区间合并的知识,就是更新时还要加上个中间合并的区间会不会造成更长的连续区间)

附线段树模板:戳这里

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define N 100010
#define LL long long
#define inf 0x3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
using namespace std;
const LL mod = 1e9 + 7;
const double eps = 1e-9;
struct node {
    int l, r;
    int sum;//1的个数
    int l0, r0, max0;
    int l1, r1, max1;
    int flag;//0,1覆盖标记
    int x_or;//异或标记
}sum[N << 2];//线段树主体
struct Segment__Tree {
    int x, y;
    void pushUp(int ans) {
        sum[ans].sum = sum[ans << 1].sum + sum[ans << 1 | 1].sum;  
        if (sum[ans << 1].l0 == (sum[ans << 1].r - sum[ans << 1].l + 1)) {
            sum[ans].l0 = sum[ans << 1].l0 + sum[ans << 1 | 1].l0;
        }
        else {
            sum[ans].l0 = sum[ans << 1].l0;
        }
        if (sum[ans << 1].l1 == (sum[ans << 1].r - sum[ans << 1].l + 1)) {
            sum[ans].l1 = sum[ans << 1].l1 + sum[ans << 1 | 1].l1;
        }
        else {
            sum[ans].l1 = sum[ans << 1].l1;
        }
        if (sum[ans << 1 | 1].r0 == (sum[ans << 1 | 1].r - sum[ans << 1 | 1].l + 1)) {
            sum[ans].r0 = sum[ans << 1].r0 + sum[ans << 1 | 1].r0;
        }
        else {
            sum[ans].r0 = sum[ans << 1 | 1].r0;
        }
        if (sum[ans << 1 | 1].r1 == (sum[ans << 1 | 1].r - sum[ans << 1 | 1].l + 1)) {
            sum[ans].r1 = sum[ans << 1].r1 + sum[ans << 1 | 1].r1;
        }
        else {
            sum[ans].r1 = sum[ans << 1 | 1].r1;
        }
        sum[ans].max0 = max(max(max(sum[ans << 1].max0, sum[ans << 1 | 1].max0), max(sum[ans].l0, sum[ans].r0)), sum[ans << 1].r0 + sum[ans << 1 | 1].l0);
        sum[ans].max1 = max(max(max(sum[ans << 1].max1, sum[ans << 1 | 1].max1), max(sum[ans].l1, sum[ans].r1)), sum[ans << 1].r1 + sum[ans << 1 | 1].l1);
    }
    void pushDown(int ans) {
        if (sum[ans].flag == 0) {
            int l = sum[ans << 1].l;
            int r = sum[ans << 1].r;
            sum[ans << 1].sum = 0;
            sum[ans << 1].l0 = r - l + 1;
            sum[ans << 1].r0 = r - l + 1;
            sum[ans << 1].max0 = r - l + 1;
            sum[ans << 1].l1 = 0;
            sum[ans << 1].r1 = 0;
            sum[ans << 1].max1 = 0;
            sum[ans << 1].flag = 0;
            l = sum[ans << 1 | 1].l;
            r = sum[ans << 1 | 1].r;
            sum[ans << 1 | 1].sum = 0;
            sum[ans << 1 | 1].l0 = r - l + 1;
            sum[ans << 1 | 1].r0 = r - l + 1;
            sum[ans << 1 | 1].max0 = r - l + 1;
            sum[ans << 1 | 1].l1 = 0;
            sum[ans << 1 | 1].r1 = 0;
            sum[ans << 1 | 1].max1 = 0;
            sum[ans << 1 | 1].flag = 0;
            sum[ans << 1].x_or = 0;
            sum[ans << 1 | 1].x_or = 0;
        }
        else if (sum[ans].flag == 1) {
            int l = sum[ans << 1].l;
            int r = sum[ans << 1].r; 
            sum[ans << 1].l0 = 0;
            sum[ans << 1].r0 = 0;
            sum[ans << 1].max0 = 0;
            sum[ans << 1].sum = r - l + 1;
            sum[ans << 1].l1 = r - l + 1;
            sum[ans << 1].r1 = r - l + 1;
            sum[ans << 1].max1 = r - l + 1;
            sum[ans << 1].flag = 1;
            l = sum[ans << 1 | 1].l;
            r = sum[ans << 1 | 1].r;
            sum[ans << 1 | 1].l0 = 0;
            sum[ans << 1 | 1].r0 = 0;
            sum[ans << 1 | 1].max0 = 0;
            sum[ans << 1 | 1].sum = r - l + 1;
            sum[ans << 1 | 1].l1 = r - l + 1;
            sum[ans << 1 | 1].r1 = r - l + 1;
            sum[ans << 1 | 1].max1 = r - l + 1;
            sum[ans << 1 | 1].flag = 1;
            sum[ans << 1].x_or = 0;
            sum[ans << 1 | 1].x_or = 0;
        }
        if (sum[ans].x_or) {
            int l = sum[ans << 1].l;
            int r = sum[ans << 1].r;
            sum[ans << 1].sum = r - l + 1 - sum[ans << 1].sum;
            swap(sum[ans << 1].l0, sum[ans << 1].l1);
            swap(sum[ans << 1].r0, sum[ans << 1].r1);
            swap(sum[ans << 1].max0, sum[ans << 1].max1);
            l = sum[ans << 1 | 1].l;
            r = sum[ans << 1 | 1].r;
            sum[ans << 1 | 1].sum = r - l + 1 - sum[ans << 1 | 1].sum;
            swap(sum[ans << 1 | 1].l0, sum[ans << 1 | 1].l1);
            swap(sum[ans << 1 | 1].r0, sum[ans << 1 | 1].r1);
            swap(sum[ans << 1 | 1].max0, sum[ans << 1 | 1].max1);
            sum[ans << 1].x_or ^= 1;
            sum[ans << 1 | 1].x_or ^= 1;
        }
        sum[ans].flag = -1;
        sum[ans].x_or = 0;
    }
    void build(int l, int r, int ans) {
        sum[ans].l = l;
        sum[ans].r = r;
        sum[ans].flag = -1;
        sum[ans].x_or = 0;
        if (l == r) {
            cin >> sum[ans].sum;
            if (sum[ans].sum == 0) {
                sum[ans].l0 = 1;
                sum[ans].r0 = 1;
                sum[ans].max0 = 1;
                sum[ans].l1 = 0;
                sum[ans].r1 = 0;
                sum[ans].max1 = 0;
            }
            else {
                sum[ans].l0 = 0;
                sum[ans].r0 = 0;
                sum[ans].max0 = 0;
                sum[ans].l1 = 1;
                sum[ans].r1 = 1;
                sum[ans].max1 = 1;
            }
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(ans);
    }
    int solve(int l, int r, int ans, int nums) {
        if (l >= x&&r <= y) {
            if (nums) {
                return sum[ans].max1;
            }
            return sum[ans].sum;
        }
        int mid = (l + r) >> 1;
        pushDown(ans);
        if (midreturn solve(rson, nums);
        }
        else if (mid >= y) {
            return solve(lson, nums);
        }
        else {
            if (nums) {
                return max(max(solve(lson, nums), solve(rson, nums)), min(sum[ans << 1].r - x + 1, sum[ans << 1].r1) + min(y - sum[ans << 1 | 1].l + 1, sum[ans << 1 | 1].l1));
            }
            return solve(lson, nums) + solve(rson, nums);
        }
    }
    void updata(int l, int r, int ans, int num) {
        if (l >= x&&r <= y) {
            if (num == 0) {
                sum[ans].sum = 0;
                sum[ans].l0 = r - l + 1;
                sum[ans].r0 = r - l + 1;
                sum[ans].max0 = r - l + 1;
                sum[ans].l1 = 0;
                sum[ans].r1 = 0;
                sum[ans].max1 = 0;
                sum[ans].flag = 0;
                sum[ans].x_or = 0;
            }
            else if(num == 1){
                sum[ans].sum = r - l + 1;
                sum[ans].l0 = 0;
                sum[ans].r0 = 0;
                sum[ans].max0 = 0;
                sum[ans].l1 = r - l + 1;
                sum[ans].r1 = r - l + 1;
                sum[ans].max1 = r - l + 1;
                sum[ans].flag = 1;
                sum[ans].x_or = 0;
            }
            else if (num == 2) {
                sum[ans].sum = r - l + 1 - sum[ans].sum;
                swap(sum[ans].l0, sum[ans].l1);
                swap(sum[ans].r0, sum[ans].r1);
                swap(sum[ans].max0, sum[ans].max1);
                sum[ans].x_or ^= 1;
                if (sum[ans].flag != -1 && sum[ans].x_or == 1) {
                    sum[ans].flag ^= 1;
                    sum[ans].x_or = 0;
                }
            }
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(ans);
        if (midelse if (mid >= y) {
            updata(lson, num);
        }
        else {
            updata(lson, num);
            updata(rson, num);
        }
        pushUp(ans);
    }
};
int main() {
    cin.sync_with_stdio(false);
    int c;
    int s;
    int n, q;
    Segment__Tree tree;
    int T;
    cin >> T;
    while (T--) {
        cin >> n >> q;
        tree.build(1, n, 1);
        while (q--) {
            cin >> s >> tree.x >> tree.y;
            tree.x++;
            tree.y++;
            if (s == 0) {
                tree.updata(1, n, 1, 0);
            }
            else if (s == 1) {
                tree.updata(1, n, 1, 1);
            }
            else if (s == 2) {
                tree.updata(1, n, 1, 2);
            }
            else if (s == 3) {
                cout << tree.solve(1, n, 1, 0) << endl;
            }
            else {
                cout << tree.solve(1, n, 1, 1) << endl;
            }
        }
    }
    return 0;
}

你可能感兴趣的:(HDU,线段树,ACM(已完结))