P6225 [eJOI 2019] 异或橙子-树状数组

题目传送门

点击查看代码
#include<bits/stdc++.h>
using namespace std;

constexpr int N = 2e5 + 10;
using LL = long long;

LL a[N], t[2][N];  // a存储原始数据,t是二维树状数组,t[0]存偶数下标,t[1]存奇数下标
LL n, q;

// 树状数组核心操作:获取最低位的1
LL lowbit(LL x)
{
    return x & (-x);
}

// 更新树状数组
// tt: 0表示偶数位置,1表示奇数位置
// x: 要更新的位置
// k: 要异或的值
void update(LL tt, LL x, LL k)
{
    for(int i = x; i <= n; i += lowbit(i))
    {
        t[tt][i] ^= k;  // 树状数组的异或更新
    }
}

// 查询树状数组前缀异或和
LL query(LL tt, LL x)
{
    LL res = 0;
    for(int i = x; i >= 1; i -= lowbit(i))
    {
        res ^= t[tt][i];  // 累加异或值
    }
    return res;    
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    cin >> n >> q;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        // 根据位置奇偶性分别存储到不同的树状数组中
        update(i & 1, i, a[i]);
    }
    
    while(q--)
    {
        LL op, x, y;
        cin >> op >> x >> y;
        if(op == 1){
            // 修改操作:先异或掉原来的值,再异或上新的值
            // 相当于 a[x] = y 的更新
            update(x & 1, x, a[x] ^ y);
            a[x] = y;
        } else {
            // 查询操作 [x, y]
            // 关键观察:只有当区间长度(y-x+1)为奇数时,结果才不为0
            // (x+y)%2==1 等价于区间长度为偶数
            if((x + y) % 2 == 1){
                // 区间长度为偶数时,所有子区间异或和会两两抵消,结果为0
                cout << 0 << '\n';
            } else {
                // 区间长度为奇数时,结果等于间隔取值的异或和
                // 具体来说,对于区间[l,r]且长度为奇数,结果是:
                // a[l] ^ a[l+2] ^ a[l+4] ^ ... ^ a[r]
                // 即所有与l奇偶性相同的位置的异或和
                cout << (query(x & 1, y) ^ query(x & 1, x - 1)) << '\n';
            } 
        }
    }

    return 0;
}
posted @ 2025-11-28 15:41  mark2025  阅读(0)  评论(0)    收藏  举报