zoukankan      html  css  js  c++  java
  • 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 ? '
    ' : ' ');
        }*/
        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
    ", Quary(L, R, 1, n, 1));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    [书目20130415]改变:28天让自己内心强大
    [引]软件著作权登记申请所需文件
    [转]动软代码生成器之模板功能介绍
    [转]C# 冒泡排序你还会吗?
    [转]细说ASP.NET Forms身份认证
    [转]listview加载性能优化ViewHolder
    [转]App for Android (2) —— Python篇
    [转]sqlserver 创建分区表
    [转]c# 四舍五入、上取整、下取整
    常用 Java 静态代码分析工具的分析与比较
  • 原文地址:https://www.cnblogs.com/chloristendika/p/10119571.html
Copyright © 2011-2022 走看看