「 Luogu P2574 」 XOR的藝術——線段樹

# 解題思路

這題不難,可是原諒我一開始的傻逼想法,一下子再給你們透露透露。node

先說怎麼作這題。ios

顯然對於 $0$ 和 $1$ 來講,異或無非也就只有兩種變化ui

  • 異或了奇數次,$0$ 就會變成 $1$,$1$ 就會變成 $0$。
  • 異或了偶數次,$0$ 和 $1$ 都不變。

那隻須要在下傳標記的時候下傳修改了幾回就能夠。spa

好,下面說說我那傻逼的操做。我在下傳標記的時候沒有給子節點的 sum 進行異或,而是隻下傳了標記,而且在回溯的時候沒有更新父節點的 sum 值。code

而後我成功的沒過樣例,然鵝這並不傻逼,改過來就好了嗎,對吧,可是,傻逼的來了,我改的時候沒有按照上面的來改,而是在進行更新時,沿途將節點打一個flag標記,僞裝這一段區間須要更改。blog

哈哈哈哈哈,而後我成功的得到了 T 四個點的好成績。get

什麼鬼,我竟然忘記更新父節點,果真仍是我太菜了。string

我決定仍是把這個代碼放上吧。 io

 

# 附上代碼

放上個人傻逼錯誤代碼class

#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\n", 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\n", query(1, l, r));
        }
    }
}T;
int main() {return 0;}
相關文章
相關標籤/搜索