描述
在給定的N個整數A1,A2……AN中選出兩個進行xor運算,得到的結果最大是多少?
輸入格式
第一行一個整數N,第二行N個整數A1~AN。
輸出格式
一個整數表示答案。
樣例輸入
3
1 2 3
樣例輸出
3
數據范圍與約定
- 對於100%的數據: N<=\(10^5\), 0<=Ai<\(2^{31}\).
題解
看到\(A_i\)最大為\(2^{31}\)很容易想到把數字拆成一個一個數位存進字典樹,而為了異或值最大,我們可以想到一個貪心,在求一個數字\(A_i\)與另一個數字\(A_j\)最大異或值時,我們要盡量讓它們對應數位上的數字不同,即0對1,1對0.
那么在trie樹檢索的時候,我們就可以盡量往與當前位相反的指針上跑,如果沒有就只能走原來的數位,根據xor運算相同得0,不同為1的運算法則,這樣是可以得到兩個數異或的最大值的
然后在存進數字的時候,我們要倒着存,這要方便后續的檢索中更新答案
綜上所述,我們可以循環i=1~n,對於每個i,前面必定已經有i-1個數字插入進了trie樹,我們每次將答案與檢索得到的答案取個最小值就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define in(i) (i=read())
using namespace std;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
return ans*f;
}
int n,m,tot,ans;
int trie[4000010][2],cnt[4000010];
void insert(int x) {
int p=0;
for(int i=31;i>=0;i--) {
int c=(x>>i)&1;
if(!trie[p][c]) trie[p][c]=++tot;
p=trie[p][c];
}
}
int search(int x) {
int p=0,ans=0;
for(int i=31;i>=0;i--) {
int c=(x>>i)&1,o=c^1;
if(trie[p][o]) p=trie[p][o],ans=ans<<1|1;
else p=trie[p][c],ans<<=1;
}
return ans;
}
int main()
{
in(n);
for(int i=1;i<=n;i++) {
int x; in(x);
ans=Max(ans,search(x));
insert(x);
}
cout<<ans<<endl;
return 0;
}
