Problem H: 位运算的游戏
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 4 Solved: 2
[ Submit][ Status][ BBS]
Description
大家都知道位运算对于学计算机的人来说是很重要的,因为他运算效率最高。自从知道了这一点之后,毛毛雨就研究了一个游戏让自己练习位运算。游戏是这样的给你一个有N个整数的数组A,然后有Q中操作,每次操作给你一个整数X,让你求X和数组A中每个元素异或的最大值。现在毛毛雨正在出线段树的题,所以需要你们帮忙了,聪明的你们能帮他解决吗?
Input
每组数据第一行输入两个整数N和Q(0<=N,Q<=100000),第二行输入A(0<=A[i]<=1000000000)数组的N个整数。
当N和Q都等于0的时候结束输入。
Output
每组数据的每个询问输出一个整数(异或的最大值),占一行。
Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
1
2
3
4
5
0 0
Sample Output
11
11
11
14
15
题目大意:给你n个数,m个操作 给你一个数分别于这n个数异或找出最大的值并输出
题目思路:这题最开始是在cf上看到的,,当时听了别人说用字典树,,然后仔细分析下,,确实可以用字典树,,字典树存每个数的二进制数,最多31位,因为要异或最大所以从最高位开始如果是0就要找1,是1就要找0,,如果找到就 ans|=(1<<i) 最后ans就是答案
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
struct trie{
struct trie *Next[2];
trie(){
for(int i=0;i<2;i++)
Next[i]=NULL;
}
};
trie *head;
void BuildTrie(int str[]){
trie *p = head;
int id;
for(int i=31;i>=0;i--){
id = str[i];
if(p->Next[id]==NULL){
p->Next[id]= new trie;
}
p=p->Next[id];
}
}
int QuarryTrie(int str[]){
int id,ans=0;
trie *p = head;
for(int i=31;i>=0;i--){
id = str[i];
if(p->Next[id^1]){
ans|=(1<<i);
p=p->Next[id^1];
}
else {
p=p->Next[id];
}
}
return ans;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)&&(n+m)){
head = new trie;
for(int i=0;i<n;i++){
int x;scanf("%d",&x);
int num[32],cnt=0;
memset(num,0,sizeof(num));
while(x){num[cnt++]=x%2;x>>=1;}
BuildTrie(num);
}
while(m--){
int x;scanf("%d",&x);
int num[32],cnt=0;
memset(num,0,sizeof(num));
while(x){num[cnt++]=x%2;x>>=1;}
printf("%d\n",QuarryTrie(num));
}
}
return 0;
}