ARC122D XOR Game(01字典树)

题目链接


题目大意:

从长度为 2n 序列中匹配 n 对数,并将匹配的两个数异或,使得的异或值最大值最小。
数据范围:n<2e5,每个数 < 2^30,都是正数。


题解

要使元素两两配对使得每对的异或和的最大值最小。先建01字典树

我们按位从高到低考虑,假设现在考虑第 i 位:

有偶数个 1 和偶数个 0:最小情况肯定是 0 对 0,1 对 1。于是分组递归下去下一位。
有奇数个 1 和奇数个 0:最小情况肯定是有一个 0 对 1 充当最大值,其他 0 对 0,1 对 1。

于是问题可以转换为:

有两组整数,各选择一个元素,求最小异或值。

const int maxn=2e5+7;
int tot=1,rt,a[32*maxn][2],n,m,cnt[32*maxn]; 
void insert(int x){
    rt=1;	cnt[1]++;
    for(int i=30;i>=0;i--){
        int k=(x>>i)&1;
        if(!a[rt][k])	a[rt][k]=++tot;
        rt=a[rt][k];	cnt[rt]++;
    }
}
/*i:位数	l,r:左右子树	f:判断是否分组了*/ 
int dfs(int i,int l,int r,bool f){
	//剪枝, !f&&!cnt[l]:未分组,且 
    if(i<0||(!f&&!cnt[l]))	return 0;
    //其左右子树都没有数,返回inf或(1<<(i+1))-1
    if(!cnt[l]||!cnt[r])	return (1<<(i+1))-1;
    
    //未分组 
    
    if(l==r){
    	//结点个数为奇数,留出一个1 ,开始分组 
    	if(cnt[a[l][0]]&1)	return dfs(i-1,a[l][0],a[l][1],1)+(1<<i);
    	//否则无贡献值,遍历其左右子树 继续不分组 
    	return max(dfs(i-1,a[l][0],a[l][0],0),dfs(i-1,a[l][1],a[l][1],0));
	}
	
	//分组后
	 
	//Alice选左子树的点,左节点的点存在,Bob选	——> 0对0 
	if(cnt[a[l][0]]&&cnt[a[r][0]])
		return min(dfs(i-1,a[l][0],a[r][0],1),dfs(i-1,a[l][1],a[r][1],1));
	//Alice选右子树的点,右节点的点存在,Bob选	——> 1对1 
	if(cnt[a[l][1]]&&cnt[a[r][1]])
		return min(dfs(i-1,a[l][0],a[r][0],1),dfs(i-1,a[l][1],a[r][1],1));
	//无法0对0,1对1,再分组,加贡献 (1<<i)
	return min(dfs(i-1,a[l][1],a[r][0],1),dfs(i-1,a[l][0],a[r][1],1))+(1<<i);
}
int main(){
	n=read();
	for(int i=0;i<2*n;i++){
		int x=read();
		insert(x);
	}
	int sum=dfs(30,1,1,0);
	out(sum);
}

/*
样例一
2
0 1 3 5
输出一
4
样例二
10
974654030 99760550 750234695 255777344 907989127 917878091 818948631 690392797 579845317 549202360 511962375 203530861 491981716 64663831 561104719 541423175 301832976 252317904 471905694 350223945
输出二
268507123
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值