题目链接~~~
题目大意
给一个有 n 个元素的数组 a,找出一个 X,满足max (ai ⊕ x)(1 <= i <= n) 的值最小。
分析
异或运算是不同则为 1。
我们对 a 中的所有元素转化为二进制,建立一个tire树。
tr[i][0] 表示它的下一位为 0 时存在。
tr[i][1] 表示它的下一位为 1 时存在。
当 i 的左右孩子都存在时,i 对应的二进制位异或后的结果一定为 1。
对于 i 的左右孩子,我们递归找最小值即可。
AC代码
#include <iostream>
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e6+5;
ll t[maxn][2];
ll a[maxn];
ll d[maxn];
ll ind = 0;
void insert(int x){
int p = 0;
for(int i = 30; i >= 0; i--){ // 从高位开始建立 trie 树
int tmp = x >> i & 1;
if(t[p][tmp] == 0) t[p][tmp] = ++ind; // 如果它的这个孩子之前不存在,给它分配一个位置
p = t[p][tmp]; // 传递孩子的位置,统计下一位
d[p] = i; // 记录这个位置表示的二进制是哪个
}
}
ll dfs(int x){
ll sum = 0;
if(t[x][0] && t[x][1]) sum = (1 << d[t[x][0]]); // 当前位必须为 1
ll res = 2e18; // 在下一位中找最小,即可满足最后的结果为最大值中的最小值。
if(t[x][0]) res = min(res, dfs(t[x][0]));
if(t[x][1]) res = min(res, dfs(t[x][1]));
if(res == 2e18) res = 0;
return sum + res;
}
int main(int argc, char** argv) {
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) insert(a[i]);
cout << dfs(0) << endl;
return 0;
}