Xor Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 1555    Accepted Submission(s): 657

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
2
 
3 2
3 4 5
1
5
 
4 1
4 6 5 6
3
 
Sample Output
Case #1:
4
3
Case #2:
4
 

题目链接:HDU 4825

学习这个也学了挺久的,苦于能百度到的详细资料甚少,尤其很多是用静态数组开写的(节省内存看起来有一点麻烦),好像这题没看见用动态链表来写的(目前还是入门阶段就一直用着new或malloc写),今天看了好一会儿的代码终于看出一点头绪了

题目本身非常经典,就是给一堆数(就记为 X吧)又给Q个询问,每次又给出一个特定的数S,求(Xi^S)的最大值。

首先异或就是两个二进制位置上的数不同就可以得到1相同则得到0,比如(10100)2^(01111)2=(11011)2,可以转换成十进制验证:20^15=27。

然后把每一个数都转换成二进制(位置要对齐,前面不足则补0),转换的长度就跟题目给的数据范围有关了,此题就33位就够了。更新字典树的顺序和过程与普通单词字典树一模一样,从左到右地遍历插入各位二进制数值,但显然next指针只有两个——next[0]与next[1],更新的最后把原来的值附到结尾节点的val上,表示这整条路对应的十进制是val。

然后如何求最大异或值呢,先要知道一般情况下正项等比数列前n-1项求和的值肯定要小于第n项的值,那也就是说最坏情况下走第x个节点而x+1~n均只能得到0的时候,也比不走x而x+1~n均得到1的情况好。

然后假设已经得到了最大异或值Max,那Max异或K就可以得到某个数Xi了,此时不知道Xi是什么,但是可以通过贪心找到它。

贪心从最高位也就是树的开始位置直接往当前二进制位值取反的节点走,走到底那个节点的val就是我们要找的Xi,这里我直接用bitset来代替位运算直观一点

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=33;
struct info
{
info *nxt[2];
int val;
info()
{
val=0;
fill(nxt,nxt+2,nullptr);
}
};
info *L;
void update(int n)
{
bitset<N> bit=n;
int i,indx;
info *cur=L;
for (i=32; i>=0; --i)
{
indx=bit[i];
if(!cur->nxt[indx])
{
info *one=new info();
cur->nxt[indx]=one;
cur=one;
}
else
cur=cur->nxt[indx];
}
cur->val=n;//末位置节点附着
}
int query(int k)
{
bitset<N> bit=k;
info *cur=L;
int indx,i;
for (i=32; i>=0; --i)
{
indx=bit[i];
if(cur->nxt[indx^1])//往取反位置走
cur=cur->nxt[indx^1];
else
cur=cur->nxt[indx];//没有的话只能继续往前走
}
return cur->val;
}
void desinfo(info *cur)//删除字典树释放内存防止MLE
{
for (int i=0; i<2; ++i)
if(cur->nxt[i])
desinfo(cur->nxt[i]);
delete cur;
}
int main(void)
{
int T,n,m,i,s,val;
scanf("%d",&T);
for (int q=1; q<=T; ++q)
{
L=new info();
scanf("%d%d",&n,&m);
for (i=0; i<n; ++i)
{
scanf("%d",&val);
update(val);
}
printf("Case #%d:\n",q);
for (i=0; i<m; ++i)
{
scanf("%d",&s);
printf("%d\n",query(s));
}
//desinfo(L);
}
return 0;
}

HDU 4825 Xor Sum(经典01字典树+贪心)的更多相关文章

  1. HDU 4825 Xor Sum(01字典树入门题)

    http://acm.hdu.edu.cn/showproblem.php?pid=4825 题意: 给出一些数,然后给出多个询问,每个询问要从之前给出的数中选择异或起来后值最大的数. 思路:将给出的 ...

  2. hdu 4825 Xor Sum(01字典树模版题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题解:一到01字典树的模版题,01字典树就是就是将一些树用二进制放到一个树上这样可以方便对整体异 ...

  3. HDU 4825 Xor Sum(01字典树)题解

    思路:先把所有数字存进字典树,然后从最高位贪心. 代码: #include<set> #include<map> #include<stack> #include& ...

  4. HDU 4825 Xor Sum (裸字典树+二进制异或)

    题目链接 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将 ...

  5. 2014百度之星资格赛—— Xor Sum(01字典树)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total ...

  6. [Hdu4825]Xor Sum(01字典树)

    Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问 ...

  7. hdu 4825 Xor Sum (01 Trie)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题面: Xor Sum Time Limit: 2000/1000 MS (Java/Others) ...

  8. hdu 4825 Xor Sum(trie+贪心)

    hdu 4825 Xor Sum(trie+贪心) 刚刚补了前天的CF的D题再做这题感觉轻松了许多.简直一个模子啊...跑树上异或x最大值.贪心地让某位的值与x对应位的值不同即可. #include ...

  9. HDU 4825 Xor Sum (模板题)【01字典树】

    <题目链接> 题目大意: 给定n个数,进行m次查找,每次查找输出n个数中与给定数异或结果最大的数. 解题分析: 01字典树模板题,01字典树在求解异或问题上十分高效.利用给定数据的二进制数 ...

随机推荐

  1. codeforces A. Group of Students 解题报告

    题目链接:http://codeforces.com/problemset/problem/357/A 题目意思:将一堆人分成两组:beginners 和 intermediate coders .每 ...

  2. 线段覆盖4(codevs 3012)

    题目描述 Description 数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段 ...

  3. Android实现电子邮箱客户端

    本文主要讲述了安卓平台上利用QQ邮箱SMTP协议,POP3协议发送与接收消息的实现 发送邮件核心代码 import java.security.Security; import java.util.D ...

  4. jquery easy ui 1.3.4 快速入门(1)

    什么是easyui jQuery EasyUI是一组基于jQuery的UI插件集合,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面.开发者不需要编写复杂 ...

  5. javascript的队列,优先队列,循环队列

    按书上的来弄的.慢慢理解了. function Queue() { var items = []; this.enqueue = function(element){ items.push(eleme ...

  6. PHP 图片水印类

    <?php /** * 加水印类,支持文字图片水印的透明度设置.水印图片背景透明. * $obj = new WaterMask($imgFileName); //实例化对象 * $obj-&g ...

  7. PHP 文件上传类

    FileUpload.;                $];                $_newname = date(,). :                             To ...

  8. jsp放在web-inf下的注意事项

    转自:http://dejazhan.iteye.com/blog/1708785 web-inf目录是不对外开放的,外部没办法直接访问到(即不能通过URL访问).所有只能通过映射来访问,比如映射为一 ...

  9. BEGIN TRAN...COMMIT TRAN 意思与用法

    BEGIN TRAN标记事务开始 COMMIT TRAN 提交事务 一般把DML语句(select ,delete,update,insert语句)放在BEGIN TRAN...COMMIT TRAN ...

  10. Zookeeper的功能以及工作原理

    1.ZooKeeper是什么?ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的 ...