题目
思路
先把所有数变为31位的二进制数。一个把所有的输入数建一个trie🌳,然后循环,从最高位开始,当存在和最高位相反的数时,走这条路(比如最高位为1,那么走0这条路会使得抑或最大),这样一直都下去,最终得出最大值。如果没有相反的数,那么只能走一样的路。
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100005;
const int M=3000000;//每个数字最多有31位数,一共100000个数,所以最多310万个数
int son[M][2],idx;//二维数组本身存的是当前结点的下标,所以总结的话son[N][x]存的就是第N的结点的x儿子的下标是多少,
//然后idx就是第一个可以用的下标
int a[N];
int n;
void insert(int x){
int p=0;
for(int i=30;i>=0;i--){//最多有30位数,最少移动0位,一共31位数
int s= x>>i & 1;
if(!son[p][s]){
son[p][s] = ++idx;//如果下标为p的点的u(0或1)这个儿子不存在,那就创建
}
p=son[p][s]; //走到当前节点
}
}
int query(int x){
int p=0;
int res=0;
for(int i=30;i>=0;i--){
int s=(x>>i) & 1;
if(son[p][!s]){ //存在相反的节点,那么走相反的节点
res += 1<<i;
p=son[p][!s];
}else{
p=son[p][s]; //如果不存在相反的节点,那么走此节点
res+=0<<i; //这一行可以取消,以为0左移以后还是0;
}
}
return res;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
insert(a[i]);
}
int res=0;
for(int i=0;i<n;i++){
res=max(res,query(a[i]));
}
cout<<res<<endl;
return 0;
}