每日一题 最大异或对--数组模拟邻接表

trie

最大异或对

#include<bits/stdc++.h>
using namespace std;

const int N=100050,M=3000000;
int ch[M][2],idx;
int a[N];
int n;
void insert(int num){
	int p = 0;
	for(int i = 30;i>=0;i--){
		int &s=ch[p][num >> i & 1];//取出ch中从节点s出发,经过边num>>i&1到达的节点
		if(!s)s=++idx;//该节点没有创建,创建节点
		p=s;//更新p 
	}
}
int query(int num){
	int p =0,res=0;
	for(int i = 30;~i;i--){
		int i_binary=num >> i & 1;//取出当前num的第i位二进制数 
		//存在和当前不同的,当前为0,存在1;当前为1,存在0 
		if(ch[p][!i_binary]){
			res+=1<<i;
			p=ch[p][!i_binary];
		}
		else{
			//res+=0>>i;//只有和当前一样的,当前是0(1),只存在0(1) 
			p=ch[p][i_binary];
		}
	} 
	return res; 
}
int main(){
	
	cin>>n;
	for(int i = 0;i<n;i++){
		cin>>a[i];
		insert(a[i]);
	}
	int res=0;
	for(int i = 0;i < n;i++) res=max(res,query(a[i]));
	cout<<res<<endl; 
	return 0;
}

 dfs,path(a,b)=path(a,root)^path(b,root),求解每个点i到root的路径异或值path(i,root)

#include<bits/stdc++.h>
using namespace std;

const int N=100050,M=3000000;
int h[N],e[N*2], c[N*2],ne[N*2],cnt;
int ch[M][2],idx;
int a[N];
int n;
void add(int u ,int v,int w){
	e[cnt]=v,c[cnt]=w,ne[cnt]=h[u],h[u]=cnt++;
}
void dfs(int u,int father, int sum){
	a[u]=sum;
	for(int i = h[u];~i;i=ne[i]){
		int j = e[i];
		if(j!=father)dfs(j,u,sum^c[i]);
	}
}
void insert(int num){
	int p = 0;
	for(int i = 30;i>=0;i--){
		int &s=ch[p][num >> i & 1];//取出ch中从节点s出发,经过边num>>i&1到达的节点
		if(!s)s=++idx;//该节点没有创建,创建节点
		p=s;//更新p 
	}
}
int query(int num){
	int p =0,res=0;
	for(int i = 30;~i;i--){
		int i_binary=num >> i & 1;//取出当前num的第i位二进制数 
		//存在和当前不同的,当前为0,存在1;当前为1,存在0 
		if(ch[p][!i_binary]){
			res+=1<<i;
			p=ch[p][!i_binary];
		}
		else{
			//res+=0>>i;//只有和当前一样的,当前是0(1),只存在0(1) 
			p=ch[p][i_binary];
		}
	} 
	return res; 
}
int main(){
	
	cin>>n;
	memset(h,-1,sizeof(h));
	for(int i = 0;i<n-1;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);
	}
	dfs(0,-1,0);
	for(int i = 0;i < n;i++)insert(a[i]);
	int res=0;
	for(int i = 0;i < n;i++) res=max(res,query(a[i]));
	cout<<res<<endl; 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值