0%

CF242E XOR on Segment

传送门

Solution

观察到 ai106<220a_i\le 10^6 <2^{20},拆位后数组变成 20 条长度为 nn01 串。开二十棵线段树分别维护这些串的区间和。

设一个串在区间 [l,r][l,r] 的和为 S,该区间与 11 异或后,新的和 S=rl+1SS'=r-l+1-S,即将区间内的 1100 互换。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <bits/stdc++.h>
#define ls k<<1
#define rs k<<1|1
using namespace std;
typedef long long ll;

const ll N = 1e5 + 10, logN = 21;

ll n, a[N], L[N << 2], R[N << 2], Q, siz[N << 2];
struct Tree {
ll sum, laz;
} T[N << 2][logN + 5];

void push_up(ll k)
{
for (int i = 0; i <= logN; i++)
T[k][i].sum = T[ls][i].sum + T[rs][i].sum;
}

void push_down(ll k)
{
for (int i = 0; i <= logN; i++) {
if (!T[k][i].laz) continue;
T[ls][i].laz ^= T[k][i].laz;
T[rs][i].laz ^= T[k][i].laz;
T[ls][i].sum = siz[ls] - T[ls][i].sum;
T[rs][i].sum = siz[rs] - T[rs][i].sum;
T[k][i].laz = 0;
}
}

void build(ll k, ll l, ll r)
{
L[k] = l; R[k] = r; siz[k] = r - l + 1;
if (l == r) {
ll num = a[l];
for (int i = 0; i <= logN; i++) {
T[k][i].sum = (num & 1);
num >>= 1;
}
return;
}
ll mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
push_up(k);
}

void modify(ll k, ll x, ll y, ll z)
{
if (x <= L[k] && R[k] <= y) {
ll num = z;
for (int i = 0; i <= logN; i++) {
if (num & 1)
T[k][i].sum = siz[k] - T[k][i].sum;
T[k][i].laz ^= (num & 1);
num >>= 1;
}
return;
}
ll mid = (L[k] + R[k]) >> 1;
push_down(k);
if (x <= mid) modify(ls, x, y, z);
if (mid < y) modify(rs, x, y, z);
push_up(k);
}

ll query(ll k, ll x, ll y)
{
ll res = 0;
if (x <= L[k] && R[k] <= y) {
for (int i = 0; i <= logN; i++)
res += (1 << i) * T[k][i].sum;
return res;
}
ll mid = (L[k] + R[k]) >> 1;
push_down(k);
if (x <= mid) res += query(ls, x, y);
if (mid < y) res += query(rs, x, y);
return res;
}

int main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
build(1, 1, n);
scanf("%lld", &Q);
while (Q--) {
ll opt, x, y, z;
scanf("%lld%lld%lld", &opt, &x, &y);
if (opt == 1) {
printf("%lld\n", query(1, x, y));
} else {
scanf("%lld", &z);
modify(1, x, y, z);
}
}
return 0;
}