P2574 XOR的艺术

线段树

题意:

给定一个01串

要求支持两种操作:

1 - 区间 xor

2 - 区间求和

做法:

普通的线段树的求和

用 rev 表示该区间是否被 xor

因为 xor 两次就相当于没有 xor

所以当区间 xor 的时候

对 rev 取反, sum = 区间长度 - sum

code:

#include <bits/stdc++.h>
using namespace std;
const int N = 2 * 100005;
int a[N], n, m, opt, L, R;
struct Stree {
    int l, r, sum; bool rev;
}tree[N * 3];

template <typename T>
inline void read(T &t) {
    t = 0; T m = 1; char ch = getchar(); 
    while(ch < '0' || ch > '9') { if(ch == '-') m = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9') { t = (t << 3) + (t << 1) + (ch & 15); ch = getchar(); }
    t *= m;
} 

void pushup(int rt) {
    tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
}

void pushdown(int rt) {
    if(tree[rt].rev) {
        tree[rt << 1].rev = !tree[rt << 1].rev, tree[rt << 1 | 1].rev = !tree[rt << 1 | 1].rev;
        tree[rt << 1].sum = (tree[rt << 1].r - tree[rt << 1].l + 1 - tree[rt << 1].sum);
        tree[rt << 1 | 1].sum = (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1 - tree[rt << 1 | 1].sum);
        tree[rt].rev = 0;
    }
}

void build(int l, int r, int rt) {
    tree[rt].l = l, tree[rt].r = r, tree[rt].sum = 0, tree[rt].rev = 0;
    if(l == r) {
        tree[rt].sum = a[l]; return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, rt << 1), build(mid + 1, r, rt << 1 | 1);
    pushup(rt);
}

int Quary(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) return tree[rt].sum;
    pushdown(rt);
    int mid = (l + r) >> 1, ans = 0;
    if(L <= mid) ans += Quary(L, R, l, mid, rt << 1);
    if(R > mid) ans += Quary(L, R, mid + 1, r, rt << 1 | 1);
    return ans;
}

void upd(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) {
        tree[rt].rev = !tree[rt].rev;
        tree[rt].sum = (r - l + 1 - tree[rt].sum);
        return;
    }
    pushdown(rt);
    int mid = (l + r) >> 1;
    if(L <= mid) upd(L, R, l, mid, rt << 1);
    if(R > mid) upd(L, R, mid + 1, r, rt << 1 | 1);
    pushup(rt);
}

int main() {
    read(n), read(m);
    for(int i = 1; i <= n; i++) {
        scanf("%1d", &a[i]);
    }
    /*r(int i = 1; i <= n; i++) {
        printf("%d%c", a[i], i == n ? '\n' : ' ');
    }*/
    build(1, n, 1);
    for(int i = 1; i <= m; i++) {
        read(opt), read(L), read(R);
        if(opt == 0) {
            upd(L, R, 1, n, 1);
        } else {
            printf("%d\n", Quary(L, R, 1, n, 1));
        }
    }
    return 0;
}
posted @ 2018-12-14 15:15  Chloristendika  阅读(174)  评论(0编辑  收藏  举报