hdu 3911, 3397 线段树 lazy tag

来源:互联网 发布:表白楼宇生成器软件 编辑:程序博客网 时间:2024/06/09 19:22

hdu 3911


题意: 
0, 1序列 
两种操作: 
1. 将一段区间内的 0 与 1 翻转 
2. 询问一段区间内最长的连续的 1 的个数

对于每个区间而言记录如下信息: 
左起连续的 1 的个数,右起连续的 1 的个数,整段区间最长的连续的 1 的个数 
左起连续的 0 的个数,右起连续的 0 的个数,整段区间最长的连续的 0 的个数 
之所以要记录 0 是为了方便翻转后信息的修改

显见,这些信息记录下来后,就不需要具体地知道每个位置究竟是 0 还是 1 了

然后再注意一下合并的细节之类的就行了

但是这道题有个很 tricky 的地方(也许只是我个人这么觉得…) 
对于 tag 的修改(在 modify 时以及 push_down 时)并不能直接置 1,要注意到 tag 的叠加性,也许这次的修改是恰好抵消了前一次的修改呢

(致谢点击打开链接,还是在看了原PO写的之后才意识到原来WA在了这里...)

AC代码如下:

#include <cstdio>#define lson ((rt) << 1)#define rson ((rt) << 1 | 1)#define maxn 100010inline max(int a, int b) { return a > b ? a : b; }inline min(int a, int b) { return a < b ? a : b; }inline midi(int a, int b) { return (a + b) >> 1; }inline swap(int& a, int& b) { int temp = a; a = b; b = temp; }struct node {    int l1, l0, r1, r0, t1, t0, len, l, r;    bool flag;}tree[maxn * 4];int n, m;void lift_up(int rt) {    tree[rt].l1 = tree[lson].l1; tree[rt].l0 = tree[lson].l0;    if (tree[rt].l1 == tree[lson].len) tree[rt].l1 += tree[rson].l1;    if (tree[rt].l0 == tree[lson].len) tree[rt].l0 += tree[rson].l0;    tree[rt].r1 = tree[rson].r1; tree[rt].r0 = tree[rson].r0;    if (tree[rt].r1 == tree[rson].len) tree[rt].r1 += tree[lson].r1;    if (tree[rt].r0 == tree[rson].len) tree[rt].r0 += tree[lson].r0;    tree[rt].t1 = max(max(tree[lson].t1, tree[rson].t1), tree[lson].r1 + tree[rson].l1);    tree[rt].t0 = max(max(tree[lson].t0, tree[rson].t0), tree[lson].r0 + tree[rson].l0);}void build(int rt, int l, int r) {    tree[rt].l = l; tree[rt].r = r; tree[rt].len = r - l + 1; tree[rt].flag = 0;    if (l == r) {        int x;        scanf("%d", &x);        tree[rt].l1 = tree[rt].r1 = tree[rt].t1 = x;        tree[rt].l0 = tree[rt].r0 = tree[rt].t0 = 1 - x;        return;    }    int mid = midi(l, r);    build(lson, l, mid); build(rson, mid + 1, r);    lift_up(rt);}void push_down(int rt) {    if (tree[rt].flag) {        swap(tree[lson].l1, tree[lson].l0); swap(tree[lson].r1, tree[lson].r0);        swap(tree[lson].t1, tree[lson].t0);        swap(tree[rson].l1, tree[rson].l0); swap(tree[rson].r1, tree[rson].r0);        swap(tree[rson].t1, tree[rson].t0);        tree[lson].flag ^= 1;        tree[rson].flag ^= 1;        tree[rt].flag = 0;    }}int query(int rt, int l, int r) {    if (tree[rt].l == l && tree[rt].r == r) return tree[rt].t1;    push_down(rt);    int mid = midi(tree[rt].l, tree[rt].r);    if (r <= mid) return query(lson, l, r);    else if (l > mid) return query(rson, l, r);    else {        int ans1 = query(lson, l, mid), ans2 = query(rson, mid + 1, r),            ans3 = min(mid - l + 1, tree[lson].r1) + min(r - mid, tree[rson].l1);        return max(max(ans1, ans2), ans3);    }}void modify(int rt, int l, int r) {    if (tree[rt].l == l && tree[rt].r == r) {        swap(tree[rt].l1, tree[rt].l0); swap(tree[rt].r1, tree[rt].r0);        swap(tree[rt].t1, tree[rt].t0);        tree[rt].flag ^= 1;        return;    }    push_down(rt);    int mid = midi(tree[rt].l, tree[rt].r);    if (r <= mid) modify(lson, l, r);    else if (l > mid) modify(rson, l, r);    else { modify(lson, l, mid); modify(rson, mid + 1, r); }    lift_up(rt);}void work() {    build(1, 1, n);    scanf("%d", &m);    for (int i = 0; i < m; ++i) {        int x, l, r;        scanf("%d%d%d", &x, &l, &r);        if (x == 0) printf("%d\n", query(1, l, r));        else modify(1, l, r);    }}int main() {    while (scanf("%d", &n) != EOF) work();    return 0;}


hdu 3397


题意: 

0, 1序列 
五种操作: 
1. 将一段区间全置 0 
2. 将一段区间全置 1 
3. 将一段区间 0, 1 翻转 
4. 询问一段区间内 1 的总数 
5. 询问一段区间内最长的连续的 1 的个数

显见对于连续的 1 的个数的处理和上一题(hdu 3911)一模一样 
而 1 的总数的记录就是最简单的那样 
所以这道题关键的地方就在于 tag 怎么处理

用了两个 tag,来分别表示 第三种操作(flag1) 和 前两种操作(flag2), 
在,分别初始化为 flag1 = 0, flag2 = -1 
(事实上,对于 flag1 的处理和上一题中一模一样)

显见,前两种操作的优先级是比第三种操作要高的,所以 
在 push_down 时,首先根据 flag2 来 push,如果 flag2 == -1,再去根据 flag1 来 push; 
在 modify 时, 
如果当前操作是前两种操作,那么直接修改flag2; 
如果当前操作是第三种操作,如果 flag2 != -1(这意味着记录下的当前段的状态是全 0 或 全 1,第三种操作进行后也是变为 全 1 或 全 0), 那么 flag2 取反;否则修改 flag1

(顺便说一句,这道题写完后根本不想检查 
然后 
一遍A的感觉真是太爽了库库库)

AC代码如下:

#include <cstdio>#define lson ((rt) << 1)#define rson ((rt) << 1 | 1)#define maxn 100010inline max(int a, int b) { return a > b ? a : b; }inline min(int a, int b) { return a < b ? a : b; }inline midi(int a, int b) { return (a + b) >> 1; }inline swap(int& a, int& b) { int temp = a; a = b; b = temp; }int n, m;struct node {    int l, r, num, l1, l0, r1, r0, t1, t0, len, flag1, flag2;}tree[maxn * 4];void lift_up(int rt) {    tree[rt].num = tree[lson].num + tree[rson].num;    tree[rt].l1 = tree[lson].l1; tree[rt].r1 = tree[rson].r1;    if (tree[rt].l1 == tree[lson].len) tree[rt].l1 += tree[rson].l1;    if (tree[rt].r1 == tree[rson].len) tree[rt].r1 += tree[lson].r1;    tree[rt].l0 = tree[lson].l0; tree[rt].r0 = tree[rson].r0;    if (tree[rt].l0 == tree[lson].len) tree[rt].l0 += tree[rson].l0;    if (tree[rt].r0 == tree[rson].len) tree[rt].r0 += tree[lson].r0;    tree[rt].t1 = max(max(tree[lson].t1, tree[rson].t1), tree[lson].r1 + tree[rson].l1);    tree[rt].t0 = max(max(tree[lson].t0, tree[rson].t0), tree[lson].r0 + tree[rson].l0);}void push_down(int rt) {    if (tree[rt].flag2 != -1) {        tree[lson].l1 = tree[lson].r1 = tree[lson].t1 = tree[lson].num = tree[rt].flag2 * tree[lson].len;        tree[lson].l0 = tree[lson].r0 = tree[lson].t0 = (1 - tree[rt].flag2) * tree[lson].len;        tree[rson].l1 = tree[rson].r1 = tree[rson].t1 = tree[rson].num = tree[rt].flag2 * tree[rson].len;        tree[rson].l0 = tree[rson].r0 = tree[rson].t0 = (1 - tree[rt].flag2) * tree[rson].len;        tree[lson].flag2 = tree[rson].flag2 = tree[rt].flag2;        tree[rt].flag2 = -1; tree[rt].flag1 = 0;        return;    }    if (tree[rt].flag1) {        swap(tree[lson].l1, tree[lson].l0); swap(tree[lson].r1, tree[lson].r0);        swap(tree[lson].t1, tree[lson].t0); tree[lson].num = tree[lson].len - tree[lson].num;        swap(tree[rson].l1, tree[rson].l0); swap(tree[rson].r1, tree[rson].r0);        swap(tree[rson].t1, tree[rson].t0); tree[rson].num = tree[rson].len - tree[rson].num;        if (tree[lson].flag2 != -1) tree[lson].flag2 = 1 - tree[lson].flag2;        else tree[lson].flag1 ^= 1;        if (tree[rson].flag2 != -1) tree[rson].flag2 = 1 - tree[rson].flag2;        else tree[rson].flag1 ^= 1;        tree[rt].flag2 = -1; tree[rt].flag1 = 0;    }}void build(int rt, int l, int r) {    tree[rt].l = l; tree[rt].r = r; tree[rt].len = r - l + 1; tree[rt].flag1 = 0; tree[rt].flag2 = -1;    if (l == r) {        int x;        scanf("%d", &x);        tree[rt].num = tree[rt].l1 = tree[rt].r1 = tree[rt].t1 = x;        tree[rt].l0 = tree[rt].r0 = tree[rt].t0 = 1 - x;        return;    }    int mid = midi(l, r);    build(lson, l, mid); build(rson, mid + 1, r);    lift_up(rt);}void modify(int rt, int l, int r, int x) {//    printf("%d\n", rt);    if (tree[rt].l == l && tree[rt].r == r) {        if (x == 0 || x == 1) {            tree[rt].num = tree[rt].l1 = tree[rt].r1 = tree[rt].t1 = x * tree[rt].len;            tree[rt].l0 = tree[rt].r0 = tree[rt].t0 = (1 - x) * tree[rt].len;            tree[rt].flag2 = x; tree[rt].flag1 = 0;        }        else {            tree[rt].num = tree[rt].len - tree[rt].num;            swap(tree[rt].l1, tree[rt].l0); swap(tree[rt].r1, tree[rt].r0);            swap(tree[rt].t1, tree[rt].t0);            if (tree[rt].flag2 != -1) tree[rt].flag2 = 1 - tree[rt].flag2;            else tree[rt].flag1 ^= 1;        }        return;    }    push_down(rt);    int mid = midi(tree[rt].l, tree[rt].r);    if (r <= mid) modify(lson, l, r, x);    else if (l > mid) modify(rson, l, r, x);    else { modify(lson, l, mid, x); modify(rson, mid + 1, r, x); }    lift_up(rt);}int query(int rt, int l, int r, int x) {//    printf("%d\n", rt);    if (tree[rt].l == l && tree[rt].r == r) {        if (x == 0) return tree[rt].num;        return tree[rt].t1;    }    push_down(rt);    int mid = midi(tree[rt].l, tree[rt].r);    if (r <= mid) return query(lson, l, r, x);    else if (l > mid) return query(rson, l, r, x);    else {        if (x == 0) return query(lson, l, mid, x) + query(rson, mid + 1, r, x);        else {            int ans1 = query(lson, l, mid, x), ans2 = query(rson, mid + 1, r, x),                ans3 = min(mid - l + 1, tree[lson].r1) + min(r - mid, tree[rson].l1);            return max(max(ans1, ans2), ans3);        }    }}void work() {    build(1, 1, n);    for (int i = 0; i < m; ++i) {        int op, l, r;        scanf("%d%d%d", &op, &l, &r); ++l; ++r;        switch (op) {            case 0:            case 1:            case 2: modify(1, l, r, op);                    break;            case 3:            case 4: printf("%d\n", query(1, l, r, op - 3)); break;        }    }}int main() {//    freopen("3397.in", "r", stdin);    int T;    scanf("%d", &T);    while (scanf("%d%d", &n, &m) != EOF) work();    return 0;}



原创粉丝点击