zoukankan      html  css  js  c++  java
  • 「 Luogu P2574 」 XOR的艺术——线段树

    # 解题思路

    这题不难,但是原谅我一开始的傻逼想法,一会儿再给大家透露透露。

    先说怎么做这题。

    显然对于 $0$ 和 $1$ 来说,异或无非也就只有两种变化

    • 异或了奇数次,$0$ 就会变成 $1$,$1$ 就会变成 $0$。
    • 异或了偶数次,$0$ 和 $1$ 都不变。

    那只需要在下传标记的时候下传修改了几次就可以。

    好,下面说说我那傻逼的操作。我在下传标记的时候没有给子节点的 sum 进行异或,而是只下传了标记,并且在回溯的时候没有更新父节点的 sum 值。

    然后我成功的没过样例,然鹅这并不傻逼,改过来就行了吗,对吧,但是,傻逼的来了,我改的时候没有按照上面的来改,而是在进行更新时,沿途将节点打一个flag标记,假装这一段区间需要更改。

    哈哈哈哈哈,然后我成功的获得了 T 四个点的好成绩。

    什么鬼,我居然忘记更新父节点,果然还是我太菜了。

    我决定还是把这个代码放上吧。 

    # 附上代码

    放上我的傻逼错误代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    int n, m;
    const int maxn = 2e5+3;
    struct node {int l, r, sum, t, tag, flag;}tree[maxn << 2];
    struct Tree {
        #define Lson (k << 1)
        #define Rson ((k << 1) | 1)
        template <typename T> inline void read(T &x) {
            x = 0; T f = 1; char c = getchar();
            while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
            while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
            x *= f;
        }
        void build(int k, int ll, int rr) {
            tree[k].l = ll, tree[k].r = rr;
            tree[k].flag = tree[k].t = 0;
            if(tree[k].l == tree[k].r) {
                scanf("%1d", &tree[k].sum);
                return ;
            }
            int mid = (tree[k].l + tree[k].r) >> 1;
            build(Lson, tree[k].l, mid);
            build(Rson, mid+1, tree[k].r);
            tree[k].sum = tree[Lson].sum + tree[Rson].sum;
        }
        void push_down(int k) {
            tree[Lson].t += tree[k].tag;
            tree[Rson].t += tree[k].tag;
            tree[Lson].tag += tree[k].tag;
            tree[Rson].tag += tree[k].tag;
            tree[k].tag = 0;
        }
        void update(int k, int L, int R) {
            if(tree[k].l >= L && tree[k].r <= R) {
                tree[k].t ++;
                tree[k].tag ++;
                return;
            }
            tree[k].flag = 1;
            if(tree[k].tag) push_down(k);
            int mid = (tree[k].l + tree[k].r) >> 1;
            if(L <= mid) update(Lson, L, R);
            if(R > mid) update(Rson, L, R);
        }
        int query(int k, int L, int R) {
            int ans = 0;
            if(tree[k].l >= L && tree[k].r <= R && tree[k].flag == 0) {
                if(tree[k].t % 2 == 1) return (tree[k].r-tree[k].l+1)-tree[k].sum;
                else return tree[k].sum;
            }
            if(tree[k].tag) push_down(k);
            int mid = (tree[k].l + tree[k].r) >> 1;
            if(L <= mid) ans += query(Lson, L, R);
            if(R > mid) ans += query(Rson, L, R);
            return ans;
        }
        Tree () {
            read(n), read(m);
            build(1, 1, n);
            int opt, l, r;
            for(int i=1; i<=m; i++) {
                read(opt), read(l), read(r);
                if(opt == 0) update(1, l, r);
                else printf("%d
    ", query(1, l, r));
            }
        }
    }T;
    int main() {return 0;}

    好,我们再来看看正确的代码

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    int n, m;
    const int maxn = 2e5+3;
    struct node {int l, r, sum, t, tag, flag;}tree[maxn << 2];
    struct Tree {
        #define Lson (k << 1)
        #define Rson ((k << 1) | 1)
        template <typename T> inline void read(T &x) {
            x = 0; T f = 1; char c = getchar();
            while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
            while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
            x *= f;
        }
        void build(int k, int ll, int rr) {
            tree[k].l = ll, tree[k].r = rr;
            tree[k].flag = tree[k].t = 0;
            if(tree[k].l == tree[k].r) {
                scanf("%1d", &tree[k].sum);
                return ;
            }
            int mid = (tree[k].l + tree[k].r) >> 1;
            build(Lson, tree[k].l, mid);
            build(Rson, mid+1, tree[k].r);
            tree[k].sum = tree[Lson].sum + tree[Rson].sum;
        }
        void push_down(int k) {
            if(tree[k].tag % 2 == 1)
                tree[Lson].sum = (tree[Lson].r-tree[Lson].l+1)-tree[Lson].sum,
                tree[Rson].sum = (tree[Rson].r-tree[Rson].l+1)-tree[Rson].sum;
            tree[Lson].tag += tree[k].tag;
            tree[Rson].tag += tree[k].tag;
            tree[k].tag = 0;
        }
        void update(int k, int L, int R) {
            if(tree[k].l >= L && tree[k].r <= R) {
                tree[k].tag ++;
                tree[k].sum = (tree[k].r-tree[k].l+1)-tree[k].sum;
                return;
            }
            if(tree[k].tag) push_down(k);
            int mid = (tree[k].l + tree[k].r) >> 1;
            if(L <= mid) update(Lson, L, R);
            if(R > mid) update(Rson, L, R);
            tree[k].sum = tree[Lson].sum + tree[Rson].sum;
        }
        int query(int k, int L, int R) {
            int ans = 0;
            if(tree[k].l >= L && tree[k].r <= R)
                return tree[k].sum;
            if(tree[k].tag) push_down(k);
            int mid = (tree[k].l + tree[k].r) >> 1;
            if(L <= mid) ans += query(Lson, L, R);
            if(R > mid) ans += query(Rson, L, R);
            return ans;
        }
        Tree () {
            read(n), read(m);
            build(1, 1, n);
            int opt, l, r;
            for(int i=1; i<=m; i++) {
                read(opt), read(l), read(r);
                if(opt == 0) update(1, l, r);
                else printf("%d
    ", query(1, l, r));
            }
        }
    }T;
    int main() {return 0;}
  • 相关阅读:
    windows下jmeter安装配置
    golang读取json配置文件
    磁盘分区、扇区等概念理解
    linux 命令笔记
    jvm静态分派和动态分派
    java实例初始化顺序
    计算机网络
    文件对比工具Meld
    IaaS、PaaS、SaaS
    USB 驱动常见名词解释
  • 原文地址:https://www.cnblogs.com/bljfy/p/9790383.html
Copyright © 2011-2022 走看看