HDU 3397 Sequence operation 线段树综合题

来源:互联网 发布:软件开发 改22 80端口 编辑:程序博客网 时间:2024/05/16 18:19

题目地址
题意:给你个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 <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#define N 100010#define LL long long#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1using 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 (mid<x) {            return 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 (mid<x) {            updata(rson, num);        }        else 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;}
原创粉丝点击