字典树的一些趣题

两道字典树的趣题

「一本通 2.3 例 2」The XOR Largest Pair -HydroOJ

我们先将所有数的二进制从高位往低位建字典树:

01字典树

然后枚举每一个 \(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;
}
posted @ 2023-10-13 14:22  DZhearMins  阅读(7)  评论(0编辑  收藏  举报