求xor值是字典树的一个经典的应用,首先我们把数用二进制表示,然后存在字典树里面,从高位到低位的存,然后查找的时候我们走不同的边(这样xor的结果会是1),如果没有不同边,那就走这个相同的边好了。
题意:给你n个数,然后再给你m询问,每次询问是找到n个数里面与这个数的xor最大的那个数。
解法:xor就可以想到用字典树了,把数拆分为二进制,然后建立字典树,接着在字典树上跑。
#include<cstdio>
#include<algorithm>
#include<cstring>
//#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define X first
#define Y second
#define cl(a,b) memset(a,b,sizeof(a))
typedef pair<long long ,long long > P;
const int maxn=4000005;
const LL inf=1LL<<45;
const LL mod=1e9+7;
struct Tree{
int Next[maxn][2];//Next[i][j]表示i的儿子节点j在树里面编号
LL End[maxn];//以编号i结束的叶子节点对应的值。
int root,L;
int newNode(){
cl(Next[L],-1);
End[L]=0;
return L++;
}
void init(){
L=0;
root=newNode();
}
void Insert(LL x){
int now=root;
for(int i=32;i>=0;i--){
int v=(x&(1LL<<i))?1:0;
if(Next[now][v]==-1){
Next[now][v]=newNode();
}
now=Next[now][v];
}
End[now]=x;
}
LL query(LL x){
int now=root;
for(int i=32;i>=0;i--){
int v=(x&(1LL<<i))?1:0;
if(Next[now][!v]!=-1){
now=Next[now][!v];
}
else {
now=Next[now][v];
}
}
return End[now];
}
};
Tree tree;
int main(){
int T;scanf("%d",&T);int cas=1;
while(T--){
int n,m;
scanf("%d%d",&n,&m);
tree.init();
for(int i=0;i<n;i++){
LL x;scanf("%lld",&x);
tree.Insert(x);
}
printf("Case #%d:\n",cas++);
while(m--){
LL x;scanf("%lld",&x);
printf("%lld\n",tree.query(x));
}
}
return 0;
}