题目链接:https://loj.ac/problem/10050
分析:
把每一个整数看作长度为32的二进制01串(最低二进制位为叶节点)。
贪心思想:在求一个数字Ai与另一个数字Aj最大异或值时,我们要尽量让它们对应数位上的数字不同,即0对1,1对0。
对于1<=i<=N,我们把A1~Ai-1对应的32位二进制串插入一颗Trie树。
综上所述,我们可以循环i=1~N次,对于每个i,前面必定已经有i-1个数字插入进了trie树,我们每次将答案与检索得到的答案取个最大值就可以了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int ch[N*32][2],n,tot;
void inser(int x)/*将x转化为01串插入Trie树中*/
{
int u=1;
for(int i=31; i>=0; i--)
{
int c=(x>>i)&1;/*将每一位转化为0或1*/
if(!ch[u][c])
ch[u][c]=++tot;
u=ch[u][c];
}
}
int quary(int x)
{
int ans=0,u=1;
for(int i=31; i>=0; i--)
{
int c=(x>>i)&1;
int o=c^1;/*将0改变为1,1改变为0*/
if(ch[u][o])/*如果它的相反数存在*/
{
ans=ans<<1|1;
u=ch[u][o];
}
else
{
ans=ans<<1;
u=ch[u][c];
}
}
return ans;
}
int main()
{
scanf("%d",&n);
int mx=0;
tot=1;
memset(ch,0,sizeof(ch));
while(n--)
{
int x;
scanf("%d",&x);
mx=max(mx,quary(x));/*对于每一个i,前面已经有i-1个数在Trie树中,可以两两异或找到最大值*/
inser(x);/*比较完后插入Trie树中*/
}
printf("%d\n",mx);
return 0;
}