HDU 4825 Xor Sum(trie树+贪心)

Xor SumTime Limit: 2000/1000 MS (Java/Others)Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 712Accepted Submission(s): 342

Problem Description

Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?

Input

输入包含若干组测试数据,每组测试数据包含若干行。输入的第一行是一个整数T(T < 10),,表示共有T组数据。每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。

Output

对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。对于每个询问,输出一个正整数K,使得K与S异或值最大。

Sample Input

23 23 4 5154 14 6 5 63

Sample Output

Case #1:43Case #2:4

题目大意:

给出n个不超过2^32的正整数,接下来有m次询问,每次输入一个正整数s,输出这n个数中的某个整数k,使得s^k的值最大。解题思路:根据异或的性质(相同得0,不同得1),如果要使得异或的值最大,那么s与k转化为二进制后要有尽量多的高位不同。这里用到了贪心的思想,我们优先考虑高位,使得高位相反,其次再考虑低位,这样才能使得异或的值最大。同时题目给出的内存比较大,然后就可以用trie树了。我们要建一个32层的二叉树,每一层的节点的两个子节点分别表示0和1,每次查询从高到低依次走相反的路径。

参考代码:

#include<map>#include<stack>#include<queue>#include<cmath>#include<vector>#include<cctype>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const double eps=1e-10;const int INF=0x3f3f3f3f;const int MAXN=5000+50;typedef long long LL;struct node{node* next[2];node(){memset(next,0,sizeof(next));}}*root;int n,m;void trie_insert(node* start,int num){node* now=start;for(int i=0; i<32; i++){int id=(num>>(31-i)&1);//从高位到低位依次取出if(now->next[id]==NULL)now->next[id]=new node();now=now->next[id];}}int trie_query(node* start,int num){node* now=start;int res=0;for(int i=0; i<32; i++){int id=(num>>(31-i)&1);//从高位到低位开始查询if(now->next[1-id])//如果与该位相反的儿子存在,那么就选择相反的儿子作为下一个位置{res=res<<1|(1-id);now=now->next[1-id];}else//如果与该位相反的分支不存在,那么就只能选择存在的儿子{res=res<<1|id;now=now->next[id];}}return res;}int main(){#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endif // ONLINE_JUDGEint tcase,f=0;scanf("%d",&tcase);while(tcase–){int t;root=new node();scanf("%d%d",&n,&m);for(int i=0; i<n; i++){scanf("%d",&t);trie_insert(root,t);}printf("Case #%d:\n",++f);for(int i=0; i<m; i++){scanf("%d",&t);printf("%d\n",trie_query(root,t));}}return 0;}

版权声明:本文为博主原创文章,未经博主允许不得转载。

你必须百分之百的把自己推销给自己。

HDU 4825 Xor Sum(trie树+贪心)

相关文章:

你感兴趣的文章:

标签云: