P6225 [eJOI2019]异或橙子

本文介绍了如何使用树状数组(BIT)解决数组区间子区间异或和的问题。通过分析异或运算的性质,发现可以分别维护奇数位置和偶数位置的数值,从而高效地计算区间内的异或和。代码示例展示了如何实现这一算法,包括修改数组元素和查询区间异或和的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

给你一个数组,然后给你两种选择,1.将x这个位置的值修改为y。2.输出x-y这个区间内的所有子区间的异或和。

思路

假如给你的区间是[2,4],意思是让你求[2,4]的子区间的异或和,那么就是2^3^4^(2^3)^(3^4)^(2^3^4),首先我们要知道异或的两个性质:1.a ^ 0 = a 2.a ^ a = a。那么上面的结果就是:2 ^ 4(因为有偶数个3,所以异或的结果是0,奇数个2和奇数个4异或的结果就是本身)。我们在来看一个例子:[2,5]的异或和:2^3^4^5^(2^3)^(3^4)^(4^5)^(2^3^4)^(3^4^5)^(2^3^4^5),我们将偶数个数的去点,那么结果就是:0,那么我们会发现一个规律:1.当给的区间的奇偶性相同时,异或的结果是[l,r]中所有于l和r奇偶性相同的位置会贡献奇数次,其他位置贡献的是偶数次,就是0,所以结果是:a_l ^ a_(l+2)……a_r。2.当区间的奇偶性不同的时候,异或的结果就是0。
那么,我们只需要用两个树状数组来保存奇数位置的数和偶数位置的数即可。
代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int n, m;
int a[N];

struct BIT
{
    int c[N];
    int lowbit(int x) { return x & -x; }
    void add(int x, int k) { for (int i = x; i <= n; i += lowbit(i)) c[i] ^= k; }
    int sum(int x)
    {
        int sum = 0;
        for (int i = x; i; i -= lowbit(i)) sum ^= c[i];
        return sum;
    }
}tr[2];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++) { scanf("%d", &a[i]); tr[i & 1].add(i, a[i]);}

    int op;
    int x, y;
    while (m --)
    {
        scanf("%d%d%d", &op, &x, &y);
        if (op == 1) { tr[x & 1].add(x, a[x] ^ y); a[x] = y; }
        else
        {
            if ((x & 1) ^ (y & 1)) puts("0");
            else printf("%d\n", (tr[x & 1].sum(y) ^ tr[x & 1].sum(x - 1)));
        }
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值