异或树状数组 || P6225 [eJOI2019] 异或橙子
输入输出样例
输入 #1
3 3 1 2 3 2 1 3 1 1 3 2 1 3
输出 #1
2 0
输入 #2
5 6 1 2 3 4 5 2 1 3 1 1 3 2 1 5 2 4 4 1 1 1 2 4 4
输出 #2
2 5 4 4
题解(引用luogu评论区):

单点修改区间查询所以适宜使用树状数组,首先异或和也满足区间前缀和性质所以只需要修改树状数组实现内部,将+改为XOR即可。
此题的关键点首先是需要从题目中捕捉到关键的规律(显然我没有耐下心看出来这个规律),其次要知道上面提到的两个异或的性质(顺带一嘴之前还做个一个异或的小性质就是异或和加法类似可以改变数字的奇偶性哦),两个关键点缺一不可,非常非常巧妙的题目。
代码 :
1 #include <bits/stdc++.h> 2 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); 3 using namespace std; 4 //using i64 = long long; 5 const string YES = "Yes"; 6 const string NO = "No"; 7 template <typename T> 8 class BIT { 9 public: 10 vector<T> c; 11 int n; 12 BIT(int _n) : n(_n) { 13 c.resize(n); 14 } 15 void modify(int x, T v) { 16 while (x < n) { 17 c[x] ^= v; 18 x |= (x + 1); 19 } 20 } 21 T query(int x) { 22 T v{}; 23 while (x >= 0) { 24 v ^= c[x]; 25 x = (x & (x + 1)) - 1; 26 } 27 return v; 28 } 29 T get(int l, int r) { 30 return query(r) ^ query(l - 1); 31 } 32 }; 33 34 int32_t main() { 35 gogo; 36 int n, q; 37 cin >> n >> q; 38 vector<int> a(n + 1); 39 for (int i = 1;i <= n;i ++) 40 cin >> a[i]; 41 BIT<int> c_odd(n + 1), c_even(n + 1); 42 for (int i = 1;i <= n;i ++) { 43 if (i & 1) 44 c_odd.modify(i, a[i]); 45 else 46 c_even.modify(i, a[i]); 47 } 48 while (q --) { 49 int o, x, y; 50 cin >> o >> x >> y; 51 if (o == 1) { 52 if (x & 1) { 53 c_odd.modify(x, a[x] ^ y); 54 a[x] = y; 55 } else { 56 c_even.modify(x, a[x] ^ y); 57 a[x] = y; 58 } 59 } else { 60 if ((x & 1) != (y & 1)) 61 cout << 0 << endl; 62 else 63 cout << ((x & 1) ? c_odd.get(x, y) : c_even.get(x, y)) << endl; 64 } 65 } 66 }

浙公网安备 33010602011771号