题目大意
给定一个长为 $n$ 的数列 $\{a_i\}$,有如下操作
- 询问区间 $[l, r]$ 上的和。
- 对 $[l, r]$ 区间上每个数异或上一个数 $x$。
分析
只需注意到异或是不进位的,我们可以单独维护数列的每一位。开二十棵线段树即可。
int main() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<SegmentTree<int>> tr;
for (int k = 0; k < 20; k++) {
tr.push_back(SegmentTree<int>(n + 1));
vector<int> tmp(n + 1);
for (int i = 1; i <= n; i++) {
if ((1 << k) & a[i])
tmp[i] = 1;
}
tr[k].build(tmp);
}
int Q;
cin >> Q;
while (Q--) {
int op, l, r;
cin >> op >> l >> r;
if (op == 1) {
ll ans = 0;
for (int k = 0; k < 20; k++) {
ans += 1ll * tr[k].query(l, r) << k;
}
cout << ans << "\n";
} else {
int x;
cin >> x;
for (int k = 0; k < 20; k++) {
if (x & (1 << k)) {
tr[k].modify(l, r, 1);
}
}
}
}
return 0;
}