bzoj 1230 lites 开关灯(线段树区间异或)

题目链接

题目大意

  略

解题思路

  区间异或,与其他操作不太一样,要考虑标记下传的时候子区间的标记的情况。

代码

const int maxn = 1e5+10;
int n, m;
struct Tree {
    int l, r, sum, lz;
} tree[maxn<<2];
inline void push_up(int rt) {
    tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;
}
inline void push_down(int rt) {
    if (tree[rt].lz==1) {
        int len = tree[rt].r-tree[rt].l+1;
        tree[rt<<1].sum = (len-(len>>1))-tree[rt<<1].sum;
        tree[rt<<1|1].sum = (len>>1)-tree[rt<<1|1].sum;
        if (tree[rt<<1].lz==-1) tree[rt<<1].lz = 1;
        else tree[rt<<1].lz ^= 1;
        if (tree[rt<<1|1].lz==-1) tree[rt<<1|1].lz = 1;
        else tree[rt<<1|1].lz ^= 1;
    }
    tree[rt].lz = -1;
}
void build(int rt, int l, int r) {
    tree[rt].l = l, tree[rt].r = r; tree[rt].lz = -1; tree[rt].sum = 0;
    if (l==r) return;
    int mid = (l+r)>>1;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid+1, r);
}
void update(int rt, int l, int r) {
    if (tree[rt].l>=l && tree[rt].r<=r) {
        int len = tree[rt].r-tree[rt].l+1;
        tree[rt].sum = len-tree[rt].sum;
        if (tree[rt].lz==-1) tree[rt].lz = 1;
        else tree[rt].lz ^= 1;
        return;
    }
    push_down(rt);
    int mid = (tree[rt].l+tree[rt].r)>>1;
    if (l<=mid) update(rt<<1, l, r);
    if (r>mid) update(rt<<1|1, l, r);
    push_up(rt);
}
int ask(int rt, int l, int r) {
    if (tree[rt].l>=l && tree[rt].r<=r) return tree[rt].sum;
    int sum = 0;
    int mid = (tree[rt].l+tree[rt].r)>>1;
    push_down(rt);
    if (l<=mid) sum += ask(rt<<1, l, r);
    if (r>mid) sum += ask(rt<<1|1, l, r);
    push_up(rt);
    return sum;
}
int main() {
    cin >> n >> m;
    build(1, 1, n);
    for (int i = 0, a, b, c; i<m; ++i) {
        scanf("%d%d%d", &a, &b, &c);
        if (a) printf("%d\n", ask(1, b, c));
        else update(1, b, c);
    }
    return 0;
}
posted @ 2020-11-01 09:43  shuitiangong  阅读(128)  评论(0编辑  收藏  举报