描述
在给定的N个整数A1,A2……AN中选出两个进行xor运算,得到的结果最大是多少?
输入格式
第一行一个整数N,第二行N个整数A1~AN。
输出格式
一个整数表示答案。
样例输入
3 1 2 3
样例输出
3
数据范围与约定
- 对于100%的数据: N<=10^5, 0<=Ai<2^31。
分析
数组开小了……,你要这样想:一个数最多开31个节点,有1e5个数,就开 31*10^5就差不多了
根据异或的性质:我们可以知道若两个位置值相异则取1,相同则取0
那我们需要最大的异或值,肯定希望每一位都尽量不同啊,那就可以在trie树上走了
对于每一个 ai 我们在trie树上每一步都试图往与当前位相反的字符指针走,如果没有的话就只能走相同位咯
但具体实现的时候,可以稍微优化一下下,每加入一个数,先在之前的trie树上走一遍,然后再将这个数插入trie树,每次都这样搞,就会避免很多重复的情况了
代码
#include<bits/stdc++.h>
#define N 100009
#define ll long long
using namespace std;
int a,n,trie[9000000][2],tot=0;//数组啊!!!!!!
void insert(int x){
int pos=0;
for(int i=31;i>=0;--i){
int c;
if(x&(1ll<<i)) c=1;
else c=0;
if(!trie[pos][c]) trie[pos][c]=++tot;
pos=trie[pos][c];
}
}
ll query(int x){
int pos=0;
ll res=0;
for(int i=31;i>=0;--i){
int c;
if(x&(1ll<<i)) c=1;
else c=0;
if(trie[pos][c^1]) pos=trie[pos][c^1],res=res|(1ll<<i);
else pos=trie[pos][c];
}
return res;
}
int main(){
scanf("%d",&n);
int i,j,k;
ll maxn=-1;
for(i=1;i<=n;++i){
scanf("%d",&a);
maxn=max(maxn,query(a));
insert(a);
}
printf("%lld",maxn);
return 0;
}