这道题第一眼看以为要把所有数拆成32位...然后每一位构建一个树状数组来操作...把自己搞得很晕。后来发现根本就不用这么麻烦,直接分析异或的性质即可。
首先对于异或,我们有 ,以及 .
我们考虑一个询问的区间 ,设 ,则显然以 为结尾的区间共有 个;以 为开头的区间共有 个,则所有包含 的区间共有 个。
若 , 的奇偶性不同,对于任意一个位置 ,它均会在答案里贡献偶数次,则 。
若 , 的奇偶性相同,则对于位置 ,它们出现的次数均为奇数次,即区间 中所有与 奇偶性相同的位置均贡献了答案。
所以我们直接维护两个树状数组,一个维护偶数位上的值,一个维护奇数位上的值,在查询时查询相应奇偶性树状数组的区间异或和即可
coding:
树状数组类:
class fenwick_tree
{
private:
int n;
vector<int> bit;
public:
fenwick_tree(const int n)
{
this->n = n;
bit.resize(n + 1, 0);
}
int lowbit(int x)
{
return x & (-x);
}
void update(int idx, int val)
{
while (idx <= n)
{
bit[idx] ^= val;
idx += lowbit(idx);
}
}
void initialize(vector<int> arr)
{
for (int i = 1; i <= n; i++)
update(i, arr[i]);
}
int query(int idx)
{
int res = 0;
while (idx)
{
res ^= bit[idx];
idx -= lowbit(idx);
}
return res;
}
int query_range(int l, int r)
{
return query(r) ^ query(l - 1);
}
};
主函数:
cin >> n >> q;
vector<int> odd(n + 1), even(n + 1);
for (int i = 1; i <= n; i++)
{
if (i % 2)
cin >> odd[i / 2 + 1];
else
cin >> even[i / 2];
}
fenwick_tree odd_ft(odd.size() - 1), even_ft(even.size() - 1);
odd_ft.initialize(odd);
even_ft.initialize(even);
int op;
while (q--)
{
cin >> op;
if (op == 1)
{
int i, j;
cin >> i >> j;
if (i % 2)
{
i = i / 2 + 1;
int old_val = odd_ft.query_range(i, i);
odd_ft.update(i, old_val ^ j);
}
else
{
i /= 2;
int old_val = even_ft.query_range(i, i);
even_ft.update(i, old_val ^ j);
}
}
else
{
int l, r;
cin >> l >> r;
int len = r - l + 1;
if (len % 2 == 0)
cout << "0\n";
else
{
int res;
if (l % 2)
{
l = l / 2 + 1, r = r / 2 + 1;
res = odd_ft.query_range(l, r);
}
else
{
l /= 2, r /= 2;
res = even_ft.query_range(l, r);
}
cout << res << "\n";
}
}
}