初试01字典树(求异或问题)
来源:互联网 发布:淘宝联盟点击赚钱 编辑:程序博客网 时间:2024/05/29 04:33
题目链接
一般01字典树用来解决区间异或和之类的问题。
异或的性质:
1. 交换律
2. 结合律,即(a^b)^c = a^(b^c))
3. 自反性,即x^x=0
4. x^0=x
其中运用最多的就是自反性。
有上述性质,对于区间异或和要知道如下性质:
XOR[l,r] = XOR[1,l-1] ^ XOR[1,r]
在查询最大异或值时我们用贪心的策略,比如我们在字典树中查询10101的最大异或值。
我们从最高位即第5位开始查(我省略掉前面的0位),由于第5位是1(对于其它的任意数,我们设为idx),之后看字典树中有没有第5为是1^1(idx^1)的数,如果有就进入0(idx^1)的节点(贪心思想,即首先保证该位异或后值为1,使异或值尽可能大),没有就进入1(idx)节点,然后从高位到低位依次这样即可。
题意:求n个数中最大异或和值的区间。有多个答案区间按字典序输出。
题解:把1-n的所有前缀异或和插入01字典树,然后按区间异或的性质扫一遍就可以了。复杂度(n*32(字典树深度))#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<iostream>#include<algorithm>#include<stack>#include<queue>#include<vector>#include<set>#include<map>#include<string>using namespace std;typedef long long ll;typedef pair<int,int>P;const int INF=0x3f3f3f3f;int n,num,ans,l,r,cnt;int ch[1000003*32][2];int idx[1000003*32];//记录字典序void init(){ num=0;cnt=1;ans=l=r=0; memset(idx,INF,sizeof(idx)); memset(ch[0],0,sizeof(ch[0]));}void Insert(int id,int x){ int k=0; for(int i=31;i>=0;i--) { int tmp=(x>>i)&1; if(!ch[k][tmp]) { memset(ch[cnt],0,sizeof(ch[cnt]));ch[k][tmp]=cnt++; } k=ch[k][tmp]; } if(id<idx[k])idx[k]=id;//保证同一个异或和的字典序最小。每一个k值代表一个异或和}void query(int id,int x){ int k=0,res=0; for(int i=31;i>=0;i--) { int tmp=(x>>i)&1;//贪心策略,从高位开始,让高位尽可能的为1,那么这个数位如果是1,那么就找0(1^1),如果是0,那么就找1(0^1); if(ch[k][tmp^1]){k=ch[k][tmp^1];res+=(1<<i);} else{k=ch[k][tmp];res+=(0<<i);}//如果并没有,那么往下贪心,这一位不变 } if(res>ans){ans=res;l=idx[k];r=id;} else if(res==ans) { if(idx[k]<l){l=idx[k];r=id;} else if(idx[k]==l&&id<r){r=id;} }}int main(){ int t,x;scanf("%d",&t); for(int ca=1;ca<=t;ca++) { scanf("%d",&n);printf("Case #%d:\n",ca); init();Insert(0,0); for(int i=1;i<=n;i++) { scanf("%d",&x);num^=x; Insert(i,num);query(i,num); } printf("%d %d\n",l+1,r);//因为XOR[l,r] = XOR[1,l-1] ^ XOR[1,r],所以l需要+1 } return 0;}
阅读全文
0 0
- 初试01字典树(求异或问题)
- 字典树初试
- 使用01字典树解决最大异或问题
- 01字典树解决异或问题学习、
- POWOJ 2475 Xor问题(异或运算+字典树)
- 【求两个数异或的最大值】01字典树求解
- hdu 4825 Xor Sum(01字典树求最大异或值)
- 01字典树专题 (解决异或最大值问题)不断更新ing~
- HDU 4825 Xor Sum(01字典树+异或)
- 异或最大值(01字典树)
- POJ 3764 The xor-longest Path 字典树求最大异或
- 字典树的应用:求数组中异或最大的两个数
- 字典树(Trie、prefix tree)及其应用(求一个数组中的最大异或值)
- 字典树处理《异或》
- uva 624 CD(01背包问题)输出最小字典序是个问题虽然题目不要求
- CSU-1216: 异或最大值-trie-01字典树
- hdu4825 Xor Sum 字典树与异或(经典)
- Vasiliy's Multiset (异或字典树)
- Airport Announcements URAL
- QT定时器使用的实例
- 算法设计与应用基础:第十四周(2)
- 【一】面向对象设计
- SpringMVC常用注解
- 初试01字典树(求异或问题)
- C语言之--volatile关键字
- vue2.0--组件通信(非vuex法)
- ArcGIS中的三种查询
- DLL链接
- 如何使用Git Bash Here,将本地项目传到github上
- 南阳OJ 数独
- 使用vue2.0 vue-router vuex 模拟ios7操作
- 微擎框架之——多级查询显示每项个数