Loading

P6225 [eJOI2019]异或橙子 树状数组 异或 位运算

给定一个数组a。

对数组a进行操作

1.修改a[i] = j

2.对区间 L , R 求每个子区间的异或和。

容易发现若 R - L 为奇数,每个数的贡献是偶数次,答案为0

若不为奇数,则奇偶相同的位数会贡献奇数次,其他贡献偶数次,即 al ^ al+2 ^ al+4 .....ar

可以用树状数组维护异或和。

由于与奇偶相关,考虑建立两颗树状数组。

注意代码中update的时候是用a[i] ^ j 来更新,这里利用了异或的性质 来实现往上更新节点。

int a[maxn];
int n;

struct BIT {
    int c[maxn];
    int ask(int x) {
        int ans = 0;
        for (; x ; x -= x & -x) ans ^= c[x];
        return ans;
    }

    void update(int x, int y) {
        for (; x <= n ; x += x & -x) c[x] ^= y;
    }
};

BIT b[2];

int main() {
    int  q;
    n = readint(), q = readint();
    for (int i = 1; i <= n; i++) {
        int x = readint();
        b[i & 1].update(i, x);
        a[i] = x;
    }
    while (q--) {
        int x = readint();
        int i = readint();
        int j = readint();
        if (x == 1) {
            b[i & 1].update(i, a[i] ^ j), a[i] = j;
        }
        else {
            if ((i + j) & 1) puts("0");
            else printf("%d\n", b[(i & 1)].ask(j) ^ b[(i & 1)].ask(i - 1));
        }
    }
}

 

posted @ 2020-08-09 11:45  MQFLLY  阅读(213)  评论(0编辑  收藏  举报