在给定的 $N$ 个整数 $A_1, A_2, cdots A_N$ 中选出两个进行异或运算,求得到的结果最大是多少。
链接
题解
Trie 模板题。
插入时将数字看作长度为 32 的二进制 01 字符串,有两种转移边即 0 和 1,构建 Trie 树。
查询每个 01 字符串(数字),每一步尝试走相反的转移边,就可以得到最大的异或值。
其实我们可以在插入字符串时顺便查询。
因为题目目标是求当 $i<j$ 求 $ A_i xor A_j$ 的最大值,可以等价于,对于每个 $i (1 leq i leq N)$ 求找到一个 $j (1 leq j < i)$ 使 $ A_i xor A_j$ 最大。当查询字符串 $A_i$ 时,每个 $A_j (1 leq j < i) $ 已经插入,符合转化后的目标,因此是正确的。
代码
#include <cstdio>
int ch[3200005][2], tot=1;
int max(int a, int b) {
return a > b ? a : b;
}
int insert(int num) {
int u = 1;
int _u = 1, res = 0;
for (int i = 1 << 30; i; i >>= 1) {
int c = (num & i) ? 1 : 0;
int _c = !c;
if (!ch[u][c]) ch[u][c] = ++tot;
u = ch[u][c];
if (ch[_u][_c]) res += i, _u = ch[_u][_c];
else _u = ch[_u][!_c];
}
return res;
}
int main() {
int n, ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int num;
scanf("%d", &num);
ans = max(ans, insert(num));
}
printf("%d
", ans);
return 0;
}