cf round613(div2) D - Dr. Evil Underscores (分治,递归)

题目链接
题目大意:给定n个数,找一个数x让x和这n个数里异或的最大值最小.输出这个最小的最大值.
位运算的题一般都是拆位运算.按位考虑怎么做
分析一下样例
1 2 3
拆位
0 1
1 0
1 1
我们要最大值最小.考虑如何去构造.要么从大到小构造要么从小到大构造(大小指的是位数)这题是要从大到小构造(可以看完做法再来想为什么).
因为要构造最大值最小.我们考虑最高位.如果说这一位上面的数有0也有1,无论我们用1异或它还是用0异或它.最后都是1.不过这里就形成了两条分支(分治的思想从此而来).看样例. 分成了 0(1) 和 1(0,1)这两条路.这两条路的解决方案和原先是一样的.只不过规模变小了.我们只需要取这两条路里面比较小的一条就可以了.而如果这一位上面全是0或者全是1,贪心的方法肯定是让它最后结果变成0.所以直接搜索下一位就好了.
不过这里有一个还要解决的问题是怎么实现0(1)和1(0,1)这样子的待选方案.
代码里使用了vector容器来做.考虑过空间会不会爆的问题.不过还好没爆…
附上代码

#define LL long long 
#define pb push_back
#include <bits/stdc++.h>
using namespace std;
LL gcd(LL a,LL b){return b == 0 ? a : gcd(b,a%b);}
const int N = 1e5+10;

int n;
int dfs(vector<int> v,int pos){
	if(pos < 0) return 0;
	vector<int> v1,v0;
	for(int i=0;i<v.size();++i){
		if( (v[i] >> pos) & 1 ) v1.pb(v[i]);
		else v0.pb(v[i]);
	}
	if(v1.empty() || v0.empty()){
		return dfs(v,pos-1);
	}
	else return (1 << pos) + min(dfs(v1,pos-1),dfs(v0,pos-1));
}
int main(){
	cin >> n;
	vector<int> v;
	int maxx = 0;
	for(int i=1;i<=n;++i){
		int x;
		cin >> x;
		maxx = max(maxx,x);
		v.pb(x);
	}
	int pos = 0;
	for(int i=29;i>=0;--i) if(maxx & (1 << i)){ pos=i;break;}
	cout << dfs(v,pos);
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值