Codeforces Round #613 (Div. 2) D. Dr. Evil Underscores(字典树+贪心)

在这里插入图片描述
题意:如题;
思路:如果才能使结果最小呢?我们假设我们选择X,把数组中每个数看成2进制(由数据范围知二进制的位数不超过30个,假设在某一位数组中所有的数都是1或者都是0,那么我们是不是肯定可以一起把这个0和1给消掉?如果该位既有0又有1呢?我们显然这一位只能取1(因为你无法消掉),所以结论就是第i位如果全是0或1,则i位是0,否是为1,跑字典树即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+1;
typedef long long ll;
ll tot=1,tree[maxn<<2][2],a[maxn];
void insert(ll x)//建立字典树 
{
	int root=1;
	for(int i=29;i>=0;--i)
	{
		int t=(x>>i)&1;
		if(!tree[root][t]) tree[root][t]=++tot;
		root=tree[root][t];
	}
}
ll solve(int dep,int root)
{
	if(dep==-1) return 0;
	if(!tree[root][0]) return solve(dep-1,tree[root][1]);//如果该位上没有0,则往1走 
	else if(!tree[root][1]) return solve(dep-1,tree[root][0]);//如果该位上有0,但没有1,则往0走 
	else return (1<<dep)+min(solve(dep-1,tree[root][0]),solve(dep-1,tree[root][1]));//该位上既有0,又有1则往两边走,同时答案的该位上一定是1,所有2的i次方,也就是这里的1<<dep 
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]),insert(a[i]);
	printf("%lld\n",solve(29,1));
}
发布了39 篇原创文章 · 获赞 0 · 访问量 1092

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/103960606