题意:
操作\(1\):求\([l,r]\)区间和。
操作\(2\):区间\([l,r]\)的数异或上\(k\)。
分析:
对区间进行位运算是没啥公式的,所以要考虑对数的每一位建线段树,记录每一位\(1\)出现的次数。询问的时候求出每一位的贡献即可。
线段树维护的是每一位\(1\)的出现次数。
区间异或:首先如果\(k\)的\(i\)位为\(0\),则异或值不变,否则异或\(i\)位的区间\([l,r]\)相当于将这个区间的\(0\)变成\(1\),\(1\)变成\(0\)。
区间或:或上某一位1才有意义
区间与:与上某一位0才有意义
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 1e5 + 5; const int mod = 1e9 + 7; int n, q, w[N]; int seg[N << 2][19], lazy[N << 2][19]; int opt, res, x, y, k; LL ans, base; void build(int rt, int l, int r, int o) { if (l == r) { seg[rt][o] += ((w[l] >> o) & 1); return ; } int mid = l + r >> 1; build(rt << 1, l, mid, o); build(rt << 1 | 1, mid + 1, r, o); seg[rt][o] = seg[rt << 1][o] + seg[rt << 1 | 1][o]; } void pushdown(int rt, int l, int r, int mid, int o) { if (lazy[rt][o]) { lazy[rt << 1][o] ^= 1; lazy[rt << 1 | 1][o] ^= 1; seg[rt << 1][o] = (mid - l + 1) - seg[rt << 1][o]; seg[rt << 1 | 1][o] = (r - mid) - seg[rt << 1 | 1][o]; lazy[rt][o] ^= 1; } } void update(int rt, int l, int r, int ql, int qr, int o) { if (l >= ql && r <= qr) { seg[rt][o] = (r - l + 1) - seg[rt][o]; lazy[rt][o] ^= 1; return ; } int mid = l + r >> 1; pushdown(rt, l, r, mid, o); if (ql <= mid) update(rt << 1, l, mid, ql, qr, o); if (qr > mid) update(rt << 1 | 1, mid + 1, r, ql, qr, o); seg[rt][o] = seg[rt << 1][o] + seg[rt << 1 | 1][o]; } int query(int rt, int l, int r, int ql, int qr, int o) { if (l >= ql && r <= qr) { return seg[rt][o]; } int mid = l + r >> 1, ans = 0; pushdown(rt, l, r, mid, o); if (ql <= mid) ans += query(rt << 1, l, mid, ql, qr, o); if (qr > mid) ans += query(rt << 1 | 1, mid + 1, r, ql, qr, o); return ans; } int main() { scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", w + i); for (int i = 0; i <= 17; i++) build(1, 1, n, i); while (q--) { scanf("%d", &opt); if (opt == 1) { scanf("%d %d", &x, &y); ans = 0, base = 1; for (int i = 0; i <= 17; i++) { ans += 1LL * base * query(1, 1, n, x, y, i); base <<= 1; } printf("%lld\n", ans); } else { scanf("%d %d %d", &x, &y, &k); for (int i = 0; i <= 17; i++) { res = ((k >> i) & 1); if (res) update(1, 1, n, x, y, i); } } } return 0; }
```