Work Applications编程题:最大异或值
来源:互联网 发布:大淘营复制软件 编辑:程序博客网 时间:2024/06/05 22:56
题目:
Description
给一个长度为n的整数序列,现在要你截取这个序列的一个前缀和一个后缀(前缀和后缀不能相交),使得前缀和后缀的异或值最大。
前缀和后缀的异或值为前缀序列中的数和后缀序列中的数,异或的结果,比如,某个序列的前缀为1、 2、 4 ,后缀为8、 16,那么它们的异或值为31.
前缀和后缀可以为空,为空时他们的值为0。
Input
有多组测试数据,请处理到文件结束。
对于每组测试数据,第一行包含一个整数n(1<=n<=100 000)。
接下来一行有n个用空格隔开的整数a1, a2, a3, ..., an (0 <= ai <= 1000 000 000 000)。
Output
对于每组测试数据输出一行,保包含一个整数,表示异或的最大的值。
Sample Input
2
1 2
3
1 2 3
2
1000 1000
Sample Output
3
3
1000
思路:
题目大意
转化后是这样的:给了一个长度为 n(1≤n≤105) 的数组,求一个不相交的前缀和后缀,使得这个前缀和后缀中的所有数的异或值最大
做法分析
如果这种题目没见过类似的话,感觉挺神的,一个长度为 105 的数组,怎么去选前缀和后缀?不过不要惊慌,题目出出来是给我们做的,总有一线生机!
先从最暴力的开始讲起:枚举每一个后缀,让他和所有不与之相交的前缀求异或值,那么转化成了:
给一个数 a,还有一堆数,怎么在这一堆数中找出一个数 b,a 和 b 的异或值最大?
想想:肯定要先把 a 和这一堆数转化成二进制数,枚举 a 的最高位,要使异或值最大,那么 b 从最高位开始,就要尽量与 a 对应的位不同,对不对?
想到这里,那就好办了:把这一堆数装进一个字典树中,当然,是从最高位开始装,然后就是在这一棵字典树中尽量找出与 a 当前位不同的数,直到找到最低位为止,那么当前路径上经过的数就是我们的数 b 了,a 异或 b 也一定是最大的
上面的问题解决了,这道题也就迎刃而解了:先把所有的数异或起来,作为最初的后缀,而前缀是 0,先插入字典树中,然后,每次将后缀“减一”,前缀“加一”,先把前缀加入字典树中,再在字典树中查询与当前的后缀异或值最大的数
总的时间复杂度 64*n
代码:
#include <iostream>#include <cstring>#include <cstdio>using namespace std;typedef long long LL;const int N=100006;LL A[N], ans, cur, New;int n;struct Trie_Tree{ struct node { int next[2]; void init() { next[0]=next[1]=-1; } } T[64*N]; int tot; void Insert(LL val) { for(int i=63, u=0; i>=0; i--) { int id=(((1LL)<<i)&(val))!=0; if(T[u].next[id]==-1) { T[tot].init(); T[u].next[id]=tot++; } u=T[u].next[id]; } } LL Find(LL val) { LL res=0; for(int i=63, u=0; i>=0; i--) { int id=(((1LL)<<i)&(val))==0; if(T[u].next[id]==-1) id^=1; res=res*2LL+(LL)id; u=T[u].next[id]; } return res; }} tree;int main(){ scanf("%d", &n); cur=0, New=0; for(int i=0; i<n; i++) scanf("%I64d", &A[i]), cur^=A[i]; tree.T[0].init(), tree.tot=1, ans=cur; tree.Insert(0LL); for(int i=0; i<n; i++) { New^=A[i], cur^=A[i]; tree.Insert(New); LL temp=tree.Find(cur); ans=max(ans, temp^cur); } printf("%I64d\n", ans); return 0;}
1
131211111
1
2
3
4
5
- Work Applications编程题:最大异或值
- 范围最大异或值
- [编程题] 异或
- COJ 1216 最大异或值
- Hrbust 1717最大异或值
- 异或最大
- Work Application 2016 笔试 编程题
- bzoj3261: 最大异或和
- bzoj3261 最大异或和
- [BZOJ3261] 最大异或和
- bzoj3261 最大异或和
- 【bzoj3261】最大异或和
- bzoj3261: 最大异或和
- NKOI 3671最大异或
- BZOJ3261 最大异或和
- 2017年院赛H题 最大异或和
- 求数组中最大的异或值 20171013
- 最大或
- Codeforces 612C Replace To Make Regular Bracket Sequence
- 2015ACM长春赛区网络赛 J题
- C++中的虚函数和存虚函数
- Spring事务配置
- C#中的String,StringBuilder 常用方法总结
- Work Applications编程题:最大异或值
- JavaScript学习--Item12 undefined 与 null
- 蓝桥杯 密文搜索 O(nlogn)实现
- addEventListener绑定事件的对象方法。
- mysql存储过程----临时表 temporary
- CDN基础服务-防盗链
- BZOJ 3207: 花神的嘲讽计划Ⅰ
- Nosql Mongodb 并发控制之乐观锁
- Java 单例模式