点击查看代码
#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;
}