intmain(){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &s[i]), s[i] ^= s[i-1]; longlong res = 0; for (int k = 0; k <= 30; k++) { int cnt[2] = {1, 0}; for (int i = 1; i <= n; i++) { int b = s[i] >> k & 1; res += (1LL << k) * cnt[b^1]; cnt[b]++; } } return !printf("%lld\n", res); }
typedeflonglong LL; constint N = 100010; structNode { int l, r; int flip; int sum[20]; } tr[N<<2]; int a[N], n, m;
voidpushup(int u){ for (int i = 0; i < 20; i++) tr[u].sum[i] = tr[u<<1].sum[i] + tr[u<<1|1].sum[i]; }
voidspread(int u, int flip){ tr[u].flip ^= flip; for (int i = 0; i < 20; i++) if (flip >> i & 1) tr[u].sum[i] = tr[u].r - tr[u].l + 1 - tr[u].sum[i]; }
voidbuild(int u, int l, int r){ tr[u].l = l, tr[u].r = r; if (l == r) { for (int i = 0; i < 20; i++) tr[u].sum[i] = a[l] >> i & 1; return; } int mid = (l+r) >> 1; build(u<<1, l, mid), build(u<<1|1, mid+1, r); pushup(u); }
voidmodify(int u, int l, int r, int x){ if (l <= tr[u].l && tr[u].r <= r) returnspread(u, x);
pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; if (l <= mid) modify(u<<1, l, r, x); if (mid+1 <= r) modify(u<<1|1, l, r, x); pushup(u); }
LL query(int u, int l, int r){ LL res = 0; if (l <= tr[u].l && tr[u].r <= r) { for (int i = 0; i < 20; i++) res += (LL)tr[u].sum[i] << i; return res; } pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; if (l <= mid) res += query(u<<1, l, r); if (mid+1 <= r) res += query(u<<1|1, l, r); return res; }
intmain(){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); build(1, 1, n); scanf("%d", &m); for (int i = 1, t, l, r, x; i <= m; i++) { scanf("%d%d%d", &t, &l, &r); if (t == 1) printf("%lld\n", query(1, l, r)); elsescanf("%d", &x), modify(1, l, r, x); } return0; }
[NOI2014] 起床困难综合症
一句话题意:给定整数 n,m 和 n 个位运算,求在 [0,m] 中哪个数字能在经过这些运算后结果最大。
structOp { char type[5]; int num; } op[N]; int n, m;
intcalc(int k, int val){ for (int i = 0; i < n; i++) { int x = op[i].num >> k & 1; switch (op[i].type[0]) { case'O': val |= x; break; case'A': val &= x; break; default: val ^= x; break; } } return val; }
intmain(){ scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%s%d", op[i].type, &op[i].num); int val = 0, res = 0; for (int i = 29; i >= 0; i--) { int res0 = calc(i, 0), res1 = calc(i, 1); // 注意位运算的优先级比逻辑运算低 if ((val ^ (1 << i)) <= m && res1 > res0) { val ^= 1 << i; res ^= res1 << i; } else { res ^= res0 << i; } } printf("%d\n", res); return0; }
[CF1878E] Iva & Pav
给定长度为 n 的数组 a,定义 f(l,r) 是 [l,r] 的区间按位和,给定 q 个查询,每个查询包含 k,l 要求找到最大的 r 使得 f(l,r)≥k,如果不存在输出 −1。