[trie]【LOJ10050】「一本通 2.3 例 2」The XOR Largest Pair
题目分析
详细讲解可参考《一本通.提高篇》p86内容。简单讲就是可以将所有的数字转化成二进制数,因此相当于长度为32的数字字符串,且数字为0和1。对于N个数,我们可以依次把这些数x,插入到trie中,然后我们找出trie中已经存在的某个数(二进制),这个数能与x异或最大。那么怎么才能找到这个最大的数呢?我们类似于trie查找,不过要“异或”查找,就是尽量选择不同的,没有节点才选相同的。这样操作完32个节点,一定能找到异或结果最大的数。然后将这个数与x以后得到一个数ans,依次更新ans的值,就能得到结果了。时间复杂度很显然是32*N.
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3.2e6+10;
int ch[maxn][2]; // 转成二进制
char s[32];
int cnt = 1; // root
void insert(char *s){
int len = 32;
int u = 1;
for(int i=0; i<len; i++){
int t = s[i]-'0';
if(!ch[u][t])
ch[u][t] = ++ cnt;
u = ch[u][t];
}
}
int find(char *s){ // 尽可能反着走, 找出这个做异或的数
int len = 32;
int u = 1;
int x = 1;
for(int i=0; i<len; i++){
int t = s[i]-'0';
int tmp = t^1;
if(ch[u][tmp]){
x = x*2+tmp;
u = ch[u][tmp];
}else{
x = x*2+t;
u = ch[u][t];
}
}
return x;
}
void change(int x){ // 转为二进制
if(x>=0) // 符号
s[0] = '0';
else{
s[0] = '1';
x = -x;
}
int k = 31; // 最后一位
while(x){
s[k--] = x%2+'0';
x /= 2;
}
while(k>=1){ // 前面补0
s[k--] = '0';
}
}
int main(){
int n, x, ans = -1;
scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%d", &x);
change(x);
insert(s);
int t = x^find(s);
ans = max(t, ans);
}
printf("%d\n", ans);
return 0;
}