CF 242E XOR on Segment
两种操作:
1、求区间和
2、对区间上的每一个数进行异或(xor)运算
直接维护区间和的话区间更新无法进行,所以,要维护的信息是区间内按位和(即每个二进制位出现的次数),那么进行xor运算的时候,只需要进行0 和 1的转换就可以了。
这样的话,就是一个基本线段树+延迟操作+维护各个二进制位信息。
#include <cstdio> #include <cstring> using namespace std; typedef long long ll; #define N 100100 int c[N<<2][20], n, q, x[N<<2]; void Up(int rt) { for (int i=0; i<20; i++) c[rt][i] = c[rt<<1][i] + c[rt<<1|1][i]; } void Down(int L, int R, int rt) { if (x[rt]) { int Mid = (L + R) >> 1; x[rt<<1] ^= x[rt]; x[rt<<1|1] ^= x[rt]; for (int i=0; i<20; i++) { if (!(x[rt] & (1<<i))) continue; c[rt<<1][i] = Mid-L+1 - c[rt<<1][i]; c[rt<<1|1][i] = R-Mid - c[rt<<1|1][i]; } x[rt] = 0; } } void build(int L, int R, int rt) { x[rt] = 0; if (L == R) { int t; scanf("%d", &t); for (int i=0; i<20; i++) if (t&(1<<i)) c[rt][i] = 1; else c[rt][i] = 0; return ; } int Mid = (L + R) >> 1; build(L, Mid, rt<<1); build(Mid+1, R, rt<<1|1); Up(rt); } void update(int l, int r, int a, int L, int R, int rt) { if (l <= L && R <= r) { x[rt] ^= a; for (int i=0; i<20; i++) { if (!(a & (1<<i))) continue; c[rt][i] = R-L+1 - c[rt][i]; } return ; } int Mid = (L+R) >> 1; Down(L, R, rt); if (l <= Mid) update(l, r, a, L, Mid, rt<<1); if (Mid < r) update(l, r, a, Mid+1, R, rt<<1|1); Up(rt); } ll query(int l, int r, int L, int R, int rt) { if (l <= L && R <= r) { ll ret = 0; for (int i=0; i<20; i++) ret += ((ll)c[rt][i])<<i; return ret; } int Mid = (L + R) >> 1; Down(L, R, rt); ll ret = 0; if (l <= Mid) ret += query(l, r, L, Mid, rt<<1); if (Mid < r) ret += query(l, r, Mid+1, R, rt<<1|1); Up(rt); return ret; } int main() { scanf("%d", &n); build(1, n, 1); scanf("%d", &q); int t, l, r, a; while (q--) { scanf("%d", &t); if (t == 1) { scanf("%d%d", &l, &r); printf("%I64d\n", query(l, r, 1, n, 1)); } else { scanf("%d%d%d", &l, &r, &a); update(l, r, a, 1, n, 1); } } return 0; }
补充:软件开发 , C++ ,