异或运算^:相同取1, 不同取0
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int son[N * 31][2], idx;//son[]记录线段树可能有1e5个31位的二进制树,所以son[31*1e5][2]
int n;
int a[N];
void insert(int x){
int p = 0;//字典树根节点
for(int i = 30; i >= 0; i -- ){//对于这个二进制数,从高位开始往树内存
int u = x >> i & 1;//取出x第i位的数(1或0)
if(!son[p][u]) son[p][u] = ++ idx;//如果这个节点,创建这个节点,节点下标为++idx;
p = son[p][u];//继续向下遍历
}
}
int query(int x){
int res = 0, p = 0;//p从根节点开始遍历,res储存结果
for(int i = 30; i >= 0; i -- ){
int u = x >> i & 1;//取出x的第i位数字(1或0)
if(son[p][!u]){//异或和运算:两数不同结果为1,所以要找和u相反的节点
res = res * 2 + !u;//如果这个点存在,就让res左移一位(res此时为二进制数),末尾加上!u
p = son[p][!u];//继续向下遍历,因为每一位都要进行异或运算,所以要沿着和x进行异或运算结果最大的树的数向下遍历
}
else{//如果和!u不存在,则只能走u节点
res = res * 2 + u;//res左移一位,末尾加上u
p = son[p][u];//继续向下遍历
}
}
return res;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++ ){
scanf("%d", &a[i]);
insert(a[i]);
}
int rv = 0;
for(int i = 0; i < n; i ++ ){
int t = query(a[i]);//令t等于和a[i]异或和最大的数
rv = max(rv, t^a[i]);//遍历选出最大值
}
printf("%d", rv);
return 0;
}