题目本身第一映像是异或操作,最容易想到for循环直接暴力遍历然后取最大值,而并不容易想到字典序这一操作,这里我们建立根节点p=0, 从根节点向下类似建立二叉树(0/1)代表各个数的各位二进制,核心思想则是对于每个数都进行查询操作,操作内容为从高位开始是否满足异或条件(因为满足异或条件的话异或结果就为1,如果存在全1的数那自然是最大的,所以其实这里或许也可以写一个if逻辑~当然这是针对特定数据,if为最大值则可直接输出 返回不用再后续遍历23333)判断逻辑为从高位遍历,在某位若存在与对应的可异或的数则优先选择,一直遍历到最底层也就是最低位。
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010,M = 3000000;
int n ;
int a[N],son[M][2],idx;
void insert(int x){
int p=0;//根节点
for(int i =30;~i;i--){//~i 取反操作 ,效果等同与>=0,
int &s = son[p][x>>i&1];//这里用引用是因为后面一行的赋值操作若不是引用则赋值对节点无效
if(!s)s=++idx;//M开了3e6,这里idx其实是字典树边的数量,因为每个数字31位长,最大可能有1e5个数,所以开//3e6;
p=s;//节点向下指针
}
}
int search(int x){
int p =0,res = 0;
for(int i =30;~i;i--){
int s = x>>i&1;//从高位开始
if(son[p][!s]){
res+=1<<i;//对于每一位所代表的值做叠加。
p=son[p][!s];//若存在可以在当前位进行异或的节点
}else p =son[p][s];
}
return res;
}
int main(){
scanf("%d",&n);
for(int i =0;i<n;i++){
scanf("%d",&a[i]);
insert(a[i]);
}int res = 0;
for(int i =0;i<n;i++)res = max(res,search(a[i]));
printf("%d\n",res);
return 0;
}