Description
给出序列 a i a_i ai, 求两两之和的异或值
Solution
按位计算
计算到第
k
k
k 位时,将
a
i
a_i
ai 按
m
o
d
2
k
+
1
mod \ 2^{k+1}
mod 2k+1 后排序
当
a
i
m
o
d
2
k
+
1
+
a
j
m
o
d
2
k
+
1
∈
[
2
k
,
2
k
+
1
−
1
]
∪
[
2
k
+
1
+
2
k
,
2
k
+
2
−
2
]
a_i \ mod \ 2^{k+1} + a_j \ mod \ 2^{k+1}\in [2^k, \ 2^{k+1} - 1] \cup [2^{k + 1} + 2^k, 2^{k+2}-2]
ai mod 2k+1+aj mod 2k+1∈[2k, 2k+1−1]∪[2k+1+2k,2k+2−2], 这两数和的第
k
k
k 位为
1
1
1
排序时每次加入一位重排可用归并排序,找区间可以用双指针
复杂度
O
(
n
l
o
g
M
a
x
)
O(n log Max)
O(nlogMax)
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int out = 0;
bool flag = false;
register char cc = getchar();
while (cc < '0' || cc > '9') {
if (cc == '-') flag = true;
cc = getchar();
}
while (cc >= '0' && cc <= '9') {
out = (out << 3) + (out << 1) + (cc ^ 48);
cc = getchar();
}
return flag ? -out : out;
}
inline void write(int x) {
if (x < 0) putchar('-'), x = -x;
if (x == 0) putchar('0');
else {
int num = 0;
char cc[15];
while (x) cc[++num] = x % 10 + 48, x /= 10;
while (num) putchar(cc[num--]);
}
putchar('\n');
}
int N, a[400010], b[400010], l1, r1, l2, r2, cnt, ans;
queue<int> q1, q2;
int main() {
N = read();
for (int i = 1; i <= N; i++) a[i] = read(), b[i] = i;
for (int k = 0; k <= 24; k++) {
for (int i = 1; i <= N; i++)
if (a[b[i]] & (1 << k)) q1.push(b[i]);
else q2.push(b[i]);
int o = 0;
while (!q2.empty()) b[++o] = q2.front(), q2.pop();
while (!q1.empty()) b[++o] = q1.front(), q1.pop();
l1 = l2 = N + 1, r1 = r2 = N, cnt = 0;
int Mod = (1 << (k + 1)) - 1;
for (int i = 1; i <= N; i++) {
o = (a[b[i]] & Mod);
while (l1 >= 2 && o + (a[b[l1 - 1]] & Mod) >= (1 << k)) l1--;
while (r1 >= 1 && o + (a[b[r1]] & Mod) >= (1 << (k + 1))) r1--;
while (l2 >= 2 && o + (a[b[l2 - 1]] & Mod) >= (1 << (k + 1)) + (1 << k)) l2--;
while (r2 >= 1 && o + (a[b[r2]] & Mod) >= (1 << (k + 2)) - 1) r2--;
if (max(i + 1, l1) <= r1) cnt += r1 - max(i + 1, l1) + 1;
if (max(i + 1, l2) <= r2) cnt += r2 - max(i + 1, l2) + 1;
}
if (cnt & 1) ans |= 1 << k;
}
write(ans);
return 0;
}