字典树的一些趣题
两道字典树的趣题
「一本通 2.3 例 2」The XOR Largest Pair -HydroOJ
我们先将所有数的二进制从高位往低位建字典树:
然后枚举每一个 \(A_i\) ,贪心地尽量走与 \(A_i\) 每一位都相反的数(这样的异或和最大),算出来的最大异或和就是答案了。
#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define S 3200005
int ch[S][2],n,a[N],tot,ans;
void write(int x){
if(x>=2)write(x>>1);
putchar((x&1)+'0');
}
void insert(int num,int x=0){
for(int i=1;i<=31;++i){
short c=((num&0x40000000)>>30);//意思是取 num 的最高位的值
if(ch[x][c]==0)ch[x][c]=++tot;
x=ch[x][c];
num<<=1;
}
}
int search(int num,int x=0,int ret=0){
for(int i=1;i<=31;++i){
short c=1-((num&0x40000000)>>30);
if(ch[x][c]==0){
ret<<=1;
c=1-c;
}else ret=((ret<<1)|1);
x=ch[x][c];
num<<=1;
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
insert(a[i]);
}
for(int i=1;i<=n;++i){
ans=max(ans,search(a[i]));
}
printf("%d\n",ans);
return 0;
}
「一本通 2.3 练习 5」The Xor-longest Path - HydroOJ
另一道字典树的趣题。
模拟一下算路径上异或和的过程,我们发现对于两个节点 \(x\) 和 \(y\) , \(x\) 到 \(y\) 路径上的异或和 \(=(x\) 到根节点路径的异或和 \()⨁(y\) 到根节点的异或和 \()\) ,这就转化成了 「一本通 2.3 练习 5」The Xor-longest Path - HydroOJ 原题,我们求的就是 (任意两条到根节点的路径的异或和的) 异或最大值。
#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define S 3200005
#define M 200005
int ch[S][2],n,a[N],tot,ans,cnt;
int fir[N],to[M],nxt[M],w[M],xorx[N];
void add(int x,int y,int z){
nxt[++cnt]=fir[x];
fir[x]=cnt;
to[cnt]=y;
w[cnt]=z;
}
void write(int x){
if(x>=2)write(x>>1);
putchar((x&1)+'0');
}
void insert(int num,int x=0){
for(int i=1;i<=31;++i){
short c=((num&0x40000000)>>30);
if(ch[x][c]==0)ch[x][c]=++tot;
x=ch[x][c];
num<<=1;
}
}
int search(int num,int x=0,int ret=0){
for(int i=1;i<=31;++i){
short c=1-((num&0x40000000)>>30);
if(ch[x][c]==0){
ret<<=1;
c=1-c;
}else ret=((ret<<1)|1);
x=ch[x][c];
num<<=1;
}
return ret;
}
void dfs(int x,int fa){
for(int e=fir[x];e;e=nxt[e]){
int u=to[e];
if(u==fa)continue;
xorx[u]=xorx[x]^w[e];
dfs(u,x);
}
}
int main(){
int x,y,z;
scanf("%d",&n);
for(int i=1;i<n;++i){
scanf("%d %d %d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dfs(1,0);
for(int i=1;i<=n;++i){
// printf("x[%d]=%d\n",i,xorx[i]);
insert(xorx[i]);
}
for(int i=1;i<=n;++i){
ans=max(ans,search(xorx[i]));
}
printf("%d",ans);
return 0;
}