AcWing 143. 最大异或对
原题链接
简单
作者:
minux
,
2020-04-24 14:17:02
,
所有人可见
,
阅读 514
解法1:贪心策略构造
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int n;
// 计算转化为二进制表示后的数码长度
int getBinLen(int x){
if(!x) return 1;
int res=0;
while(x){
x>>=1;
res++;
}
return res;
}
// 贪心算法
int main(){
memset(a, 0x00, sizeof a);
cin>>n;
int MAX=INT32_MIN; // 记录元素中的最大值
for(int i=0; i<n; ++i){
cin>>a[i];
MAX =max(MAX, a[i]);
}
int L = getBinLen(MAX);
int mXOR=0; // 记录最大异或值
int cXOR=0; // 记录当前可以出现的最大异或值
unordered_set<int> PRE;
for(int i=L-1; i>=0; --i){
mXOR<<=1;
cXOR = mXOR | 0x01;
PRE.clear();
for(int j=0; j<n; ++j) PRE.insert(a[j]>>i);
for(auto it=PRE.begin(); it!=PRE.end(); ++it){
if(PRE.count(*it^cXOR)){
mXOR = cXOR;
break;
}
}
}
cout<<mXOR<<endl;
return 0;
}
解法2:Trie
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int M=3e6+5;
int n;
int a[N];
int SON[M][2];
int idx;
// 向Trie中插入数据, 从高位向低位插入
void insert(int x){
int p=0;
for(int i=30; i>=0; --i){
int &b = SON[p][x>>i & 0x01];
if(!b) b=++idx;
p=b;
}
}
// 在Trie中查询数据
int query(int x){
int p=0, res=0;
for(int i=30; i>=0; --i){
int b=x>>i&0x01; // 取出第i位数码
if(SON[p][!b]){ // 贪心策略, 尽量向不同于b的方向走, 极大化xor值
res+=1<<i;
p=SON[p][!b];
}
else p=SON[p][b]; // 如果不存在与b不同的方向, 走b方向
}
return res;
}
int main(){
memset(a, 0x00, sizeof a);
idx=0;
cin>>n;
int res=0;
for(int i=0; i<n; ++i){
cin>>a[i];
insert(a[i]);
res =max(res, query(a[i]));
}
// for(int i=0; i<n; ++i) res = max(res, query(a[i]));
cout<<res;
return 0;
}