题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825
题意:给出n个数,再给你m个数,问这m个数中分别能在这个n个数中找到能使这两个数的异或值最大的那个数。
暴力肯定爆时间,毫无疑问。
所以这道题我们要考虑建立字典树进行贪心来处理,很明显异或运算找最大值是要从高位开始,找有没有与目标数相应位置上不同的值,能找到就取,找不到就不取,这样从高位下来肯定是能达到最大值的,关于怎么从最高位开始找,我们就要借助字典树进行处理。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL __int64
using namespace std;
const int maxn = 1000000+2;
int tree[maxn<<2][2],cnt[maxn<<2],tot;
LL a[maxn];
void insertTrie(LL num,int id)
{
int now = 0;
for(int i=32; i>=0; i--)
{
int w = (num&(1LL<<i)) > 0;
if(tree[now][w] == 0)
{
tree[now][w] = ++tot;
memset(tree[tot],0,sizeof(tree[tot]));
cnt[tot] = 0;
}
now = tree[now][w];
}
cnt[now] = id;
}
int searchTrie(LL num)
{
int now = 0;
for(int i=32; i>=0; i--)
{
int w = (num&(1LL<<i)) > 0;
if(tree[now][!w]) now = tree[now][!w];
else now = tree[now][w];
}
return cnt[now];
}
int main()
{
int T,t=0;
scanf("%d",&T);
while(T--)
{
memset(tree[0],0,sizeof(tree[0]));
tot = 0;
printf("Case #%d:\n",++t);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%I64d",&a[i]);
insertTrie(a[i],i);
}
for(int i=0; i<m; i++)
{
LL s;
scanf("%I64d",&s);
printf("%I64d\n",a[searchTrie(s)]);
}
}
return 0;
}