字典树--Xor问题
来源:互联网 发布:sql count 用法 编辑:程序博客网 时间:2024/06/05 19:38
字典树大家都知道吧,如果不知道可以看这里,我的模板写得还是不错的:
字符串–Trie树(字典树)
接下来我们先看一个问题,通过这个问题来了解Xor这个运算的基本性质:
洛谷 P2420 让我们异或吧
题目大意:给定一棵带权树,多次询问两点之间边权异或和。
性质:a^x^x=a,其中^代表Xor运算,证明略。
利用这条性质,我们可以任取一点为根,通过一次dfs算出每个点到根节点的异或和val[u],假设每次询问的点是u,v,则答案就是val[u]^val[v]。
过程:
此题代码:
//Âå¹È2420 ÈÃÎÒÃÇÒì»ò°É #include<cstdio>#include<algorithm>#define ll long longusing namespace std;inline int read(){ int x=0;char ch=' '; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x;}struct edge{ int to,next,w;}e[200001];int n,m,tot;int head[100001];int v[100001];int st[100001][20];int dep[100001];void dfs(int x,int fa){ st[x][0]=fa; for(int i=head[x];i;i=e[i].next){ int u=e[i].to; if(u==fa)continue; v[u]=v[x]^e[i].w; dep[u]=dep[x]+1; dfs(u,x); }}inline void addedge(int x,int y,int l){ e[++tot].to=y;e[tot].next=head[x];e[tot].w=l;head[x]=tot;}int main(){ n=read(); for(int i=1;i<=n-1;i++){ int x=read(),y=read(),l=read(); addedge(x,y,l);addedge(y,x,l); } dfs(1,0); m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(); int ans=v[x]^v[y]; printf("%d\n",ans); } return 0;}
接下来就是正题了——如何用字典树来解决Xor问题?
题目链接:Xor Sum
整体思路:Trie树+贪心
我们要选出一个数来使它和另一个数的异或和最大,那么当然要转二进制来看了。
转了二进制之后我们可以发现高位的值比所有低位的值相加还要大,那么就有贪心思路了:
建立一棵01Trie(每个点只有0和1两个儿子),然后将每个初始数字从高位到低位按位插入进来,然后每次查询时每一步尽量走和它那一位不同的方向,最后输出即可。
此题代码:
//hdu4825 Xor Sum#include<cstdio>#include<cstring>#define ll long longusing namespace std;inline int read(){ int x=0;char ch=' '; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x;}int n,m,tot;int ch[3100001][2];int val[3100001];void insert(int x){ int u=0; for(int i=31;i>=0;i--){ int c=(x>>i)&1; if(!ch[u][c]){ ch[u][c]=++tot; } u=ch[u][c]; } val[u]=x;}int find(int x){ int u=0; for(int i=31;i>=0;i--){ int c=(x>>i)&1; if(ch[u][c^1]){ u=ch[u][c^1]; } else{ u=ch[u][c]; } } return val[u];}int main(){ int T=read(); int k=1; while(T--){ printf("Case #%d:\n",k++); memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); tot=0; n=read();m=read(); for(int i=1;i<=n;i++){ insert(read()); } for(int i=1;i<=m;i++){ printf("%d\n",find(read())); } } return 0;}
接下来我们将第一个问题和第二个问题结合在一起来看一个题;
题目链接:The xor-longest Path
题目大意:给定一棵树,求最大异或路径。
思路:我们可以每次固定一个点,寻找和它异或路径最大的点,更新答案。这时问题就转化成了在树上已知一个点如何找另一个点和它异或路径最大。
结合T1和T2,那么我们可以表示出两点间的异或路径:val(u)^val(v),其中因为我们已经固定了一个点了,那么就是要找一个值和已知值异或值最大了,这就是T2的问题。
方案就很明显了,dfs求出每个点到根节点的异或值,然后将这些值插入到一棵01Trie中,枚举每个点找从这个点出发的最大异或路径,并更新答案。
此题代码:
//poj3764 The xor-longest Path#include<cstdio>#include<algorithm>#include<cstring>#define ll long longusing namespace std;int v[100001];int ch[3100001][2];int n;struct edge{ int to,next,w;}e[200001];int head[100001];void dfs(int x,int fa){ for(int i=head[x];i;i=e[i].next){ int u=e[i].to; if(u==fa)continue; v[u]=v[x]^e[i].w; dfs(u,x); }}int tot;inline void addedge(int x,int y,int l){ e[++tot].to=y; e[tot].next=head[x]; head[x]=tot; e[tot].w=l;}void insert(int x){ int u=0; for(int i=30;i>=0;i--){ int c=(x>>i)&1; if(!ch[u][c]){ ch[u][c]=++tot; } u=ch[u][c]; }}int find(int x){ int u=0;int ans=0; for(int i=30;i>=0;i--){ int c=(x>>i)&1; if(ch[u][c^1]){ ans+=(1<<i); u=ch[u][c^1]; } else{ u=ch[u][c]; } } return ans;}int main(){ while(scanf("%d",&n)==1){ memset(ch,0,sizeof(ch)); memset(v,0,sizeof(v)); memset(head,0,sizeof(head)); tot=0; for(int i=1;i<=n-1;i++){ int x,y,l; scanf("%d %d %d",&x,&y,&l); addedge(x,y,l); addedge(y,x,l); } dfs(0,-1); for(int i=0;i<n;i++){ insert(v[i]); } tot=0; int ans=0; for(int i=0;i<n;i++){ ans=max(ans,find(v[i])); } printf("%d\n",ans); } return 0;}
- 字典树--Xor问题
- 2475: Xor问题(字典树)
- POWOJ 2475 Xor问题(异或运算+字典树)
- HDU4825 Xor Sum 字典树
- hdu4825 Xor Sum 【字典树】
- 『字典树』xor
- nyoj - 947(Max Xor)字典树
- 字典树-百度之星-Xor Sum
- hdu 4825 Xor Sum(字典树)
- 【01字典树】HDU 4825 Xor Sum
- HDU4825 - Xor Sum(Trie 字典树)
- POJ_3764_The xor-longest Path(01字典树)
- 【字典树】 HDOJ 4825 Xor Sum
- Xor Sum(字典树加贪心)
- 字典树 hdu5269 ZYB loves Xor I
- hdu 4825 Xor Sum(字典树)
- POJ 3764 树上XOR 贪心+字典树
- POJ3764 The xor-longest Path(字典树)
- Leetcode 561 Array Partition I
- 前端技术介绍,跟我学响应式布局
- 关于pod导入protocolBuffers使用问题
- Leetcode 605 Can Place Flowers
- 1464:最低等级
- 字典树--Xor问题
- 数据库事务四大特征及隔离级别
- uva 11582 lrj-P316 斐波那契大数
- HBase 2.0 新特性& HBaseCon Asia 2017 参会总结
- C# Winform实现捕获窗体最小化、最大化、关闭按钮事件的方法,可通过重写WndProc来实现
- Leetcode 665 Non-decreasing Array
- 【学习摘记】马士兵JAVASCRIPT_课时10-12_收尾及精华整理
- JEECG 3.7.1 非Maven版本源码下载,企业级JAVA快速开发平台
- Leetcode 674 Longest Continuous Increasing Subsequence