cf242 E
题意:
$n$ 个数 $a_i$,
两种询问
$1, l, r$ 查询 $[l, r]$ 的和
$2, l, r, x$ 将区间 $[l, r]$ 所有数异或 $x$
建立 $30$ 课线段树
第 $i$ 颗线段树维护所有 $a$ 二进制的第 $i$ 为上的数字 $0, 1$
异或操作分别以 $x$ 的二进制相应位异或相应线段树
可见只有当 $x$ 的二进制位为 $1$ 是操作有效
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string> using namespace std; #define LL long long #define gc getchar() inline int read() {int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;} inline LL read_LL() {LL x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;} #undef gc const int N = 1e5 + 10; int Size[N << 2]; int n, m, Ans; #define lson jd << 1 #define rson jd << 1 | 1 struct Node { int W[N << 2], F[N << 2]; void Push_down(int jd) { F[lson] ^= 1, F[rson] ^= 1; W[lson] = Size[lson] - W[lson]; W[rson] = Size[rson] - W[rson]; F[jd] = 0; } void Push_up(int jd) { W[jd] = W[lson] + W[rson]; } void Sec_G(int l, int r, int jd, int x, int y) { if(x <= l && r <= y) { F[jd] ^= 1; W[jd] = Size[jd] - W[jd]; return ; } if(F[jd]) Push_down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_G(l, mid, lson, x, y); if(y > mid ) Sec_G(mid + 1, r, rson, x, y); Push_up(jd); } void Sec_A(int l, int r, int jd, int x, int y) { if(x <= l && r <= y) { Ans += W[jd]; return ; } if(F[jd]) Push_down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_A(l, mid, lson, x, y); if(y > mid) Sec_A(mid + 1, r, rson, x, y); } } Tree[35]; void Build_tree(int l, int r, int jd) { Size[jd] = r - l + 1; if(l == r) { int x = read(); for(int i = 0; (1 << i) <= x; i ++) { Tree[i + 1].W[jd] = (bool) ((1 << i) & x); } return ; } int mid = (l + r) >> 1; Build_tree(l, mid, lson), Build_tree(mid + 1, r, rson); for(int i = 1; i <= 30; i ++) { Tree[i].W[jd] = Tree[i].W[lson] + Tree[i].W[rson]; } } int main() { n = read(); Build_tree(1, n, 1); m = read(); for(; m; m --) { int opt = read(), l = read(), r = read(); if(opt == 2) { int x = read(); for(int i = 0; (1 << i) <= x; i ++) { if(((1 << i) & x)) { Tree[i + 1].Sec_G(1, n, 1, l, r); } } } else { LL Answer = 0; for(int i = 1; i <= 30; i ++) { Ans = 0; Tree[i].Sec_A(1, n, 1, l, r); Answer += (1ll * Ans * (LL) pow(2, i - 1)); } cout << Answer << "\n"; } } return 0; }