zoukankan      html  css  js  c++  java
  • FOJ 2105 Digits Count

    题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作。

    思路:因为化成二进制就4位可以建4颗线段树,每颗代表一位二进制。

    and 如果该为是1  直接无视,是0则成段赋值为0;

    or  如果是0 无视,是1则成段赋值为1;

    xor 成段亦或,1个数和0个数交换;

    sum 求和;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include <iostream>
    #define N 1000050
    #define debug(x) printf(#x"= %d
    ",x);
    using namespace std;
    int sum[4][N * 4], flag[4][N * 4], Xor[4][N * 4];
    int a[N];
    void pushup(int i, int now) {
        sum[now][i] = sum[now][i << 1] + sum[now][i << 1 | 1];
    }
    void pushdown(int i, int now, int l, int r) {
    
        int mid = (l + r) >> 1;
        if (flag[now][i] != -1) {
            flag[now][i << 1] = flag[now][i << 1 | 1] = flag[now][i];
            sum[now][i << 1] = (mid - l + 1) * flag[now][i];
            sum[now][i << 1 | 1] = (r - mid) * flag[now][i];
            Xor[now][i << 1] = Xor[now][i << 1 | 1] = 0;
            flag[now][i] = -1;
        }
        if (Xor[now][i]) {
            Xor[now][i << 1] ^= 1;
            sum[now][i << 1] = (mid - l + 1) - sum[now][i << 1];
            Xor[now][i << 1 | 1] ^= 1;
            sum[now][i << 1 | 1] = (r - mid) - sum[now][i << 1 | 1];
            Xor[now][i] = 0;
        }
    }
    void build(int l, int r, int i, int now) {
    
        flag[now][i] = -1;
        Xor[now][i] = 0;
        if (l == r) {
            sum[now][i] = ((a[l] >> now) & 1);
            return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, i << 1, now);
        build(mid + 1, r, i << 1 | 1, now);
        pushup(i, now);
    }
    void update(int l, int r, int pl, int pr, int type, int va, int i, int now) {
        if (l >= pl && r <= pr) {
            if (type == 1) {
                sum[now][i] = (r - l + 1) * va;
                flag[now][i] = va;
                Xor[now][i] = 0;
            } else {
                sum[now][i] = (r - l + 1 - sum[now][i]);
                Xor[now][i] ^= 1;
            }
            return;
        }
        pushdown(i, now, l, r);
        int mid = (l + r) >> 1;
        if (pl <= mid)
            update(l, mid, pl, pr, type, va, i << 1, now);
        if (pr > mid)
            update(mid + 1, r, pl, pr, type, va, i << 1 | 1, now);
        pushup(i, now);
    }
    
    int query(int l, int r, int pl, int pr, int i, int now) {
        if (l >= pl && r <= pr) {
            return sum[now][i];
        }
        pushdown(i, now, l, r);
        int mid = (l + r) >> 1;
        int tmp = 0;
        if (pl <= mid)
            tmp += query(l, mid, pl, pr, i << 1, now);
        if (pr > mid)
            tmp += query(mid + 1, r, pl, pr, i << 1 | 1, now);
        pushup(i, now);
        return tmp;
    }
    int main() {
        int n, m, tt;
        scanf("%d", &tt);
        while (tt--) {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; ++i)
                scanf("%d", &a[i]);
            for (int i = 0; i < 4; ++i)
                build(1, n, 1, i);
            while (m--) {
                char s[10];
                scanf(" %s", s);
                if (strcmp(s, "OR") == 0) {
                    int x, y, z;
                    scanf("%d%d%d", &x, &y, &z);
                    y++;
                    z++;
                    for (int i = 0; i < 4; ++i) {
                        if ((x >> i) & 1) {
                            update(1, n, y, z, 1, 1, 1, i);
                        }
                    }
                } else if (strcmp(s, "AND") == 0) {
                    int x, y, z;
                    scanf("%d%d%d", &x, &y, &z);
                    y++;
                    z++;
                    for (int i = 0; i < 4; ++i) {
                        if (((x >> i) & 1) == 0) {
                            update(1, n, y, z, 1, 0, 1, i);
                        }
                    }
                } else if (strcmp(s, "XOR") == 0) {
                    int x, y, z;
                    scanf("%d%d%d", &x, &y, &z);
                    y++;
                    z++;
                    for (int i = 0; i < 4; ++i) {
                        if (((x >> i) & 1)) {
                            update(1, n, y, z, 2, 1, 1, i);
                        }
                    }
                } else {
                    int x, y;
                    scanf("%d%d", &x, &y);
                    x++;
                    y++;
                    int ans=0;
                    for (int i = 0; i < 4; ++i) {
                        ans+=query(1,n,x,y,1,i)*(1<<i);
                    //    debug(ans);
                    }
                    printf("%d
    ",ans);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    shell中单引号、双引号、反斜杠简说
    shell脚本
    求素数
    SqlBulkCopy高效写入数据库Demo
    地图面面观之百望山
    FileUpload控件客户端验证
    如何将shapefile进行拆分
    Python 字符串操作
    如何重装oracle
    资料
  • 原文地址:https://www.cnblogs.com/L-Ecry/p/3879576.html
Copyright © 2011-2022 走看看