在给定的 N 个整数 A1,A2……AN 中选出两个数进行 xor(异或)运算,得到的结果最大是多少?
/*
最大异或对
相同为0,不同为1
把每个数看作31位的二进制数用Trie树来存储,从高位开始遍历寻找每一位异或为1的分支,到叶节点为止
更高位为1的数更大
先查找与该数异或最大的数,然后插入该数,和自己异或为0 (也可以先全部插入然后再查找异或最大的数)
本题先插入再查询,避免一开始空集的判断
如果有两个分支,优先选择异或更大的分支;如果只有一个分支,就直接走该分支
c++每秒大概1e7 ~ 1e8次运算
*/
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10, M = 31 * N; // M:最大的节点数
// 读入数据
int n, a[N];
int son[M][2], idx = 0;
// 插入
void insert(int x)
{
int p = 0;
for(int i = 30; i >= 0; i--)
{
int u = x >> i & 1; // 右移,取第i位的数
if(!son[p][u]) son[p][u] = ++ idx;
p = son[p][u];
}
}
// 查询与x异或最大的数
int query(int x)
{
int p = 0, res = 0;
for(int i = 30; i >= 0; i--)
{
int u = x >> i & 1;
// 更高位异或为1的数更大;如果有,优先选择
if(son[p][!u])
{
p = son[p][!u];
res = res * 2 + !u; // 相当于左移
}
else
{
// 如果只有一个分支
p = son[p][u];
res = res * 2 + u;
}
}
return res;
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
int res = 0;
for(int i = 0; i < n; i++)
{
insert(a[i]);
res = max(res, a[i] ^ query(a[i]));
}
printf("%d\n", res);
return 0;
}