CodeForces 1285D Dr. Evil Underscores

Description CodeForces 1285D

描述

给一个长度为 $n$ 的数组 $a$,试找到一个 $X$,使得 $\max\limits_{1\le i \le n} (a_i \oplus X)$ 最小,输出这个最小值即可。

输入

第一行一个数 $n(1 \le n \le 10^5)$,接下来第二行 $n$ 个数表示 $a$ 数组 $(0\le a_i \le 2^{30} - 1)$。

输出

一行一个数,表示所求最小值。

样例

输入1

3
1 2 3

输出1

2

输入2

2
1 5

输出2

4

解释

在第一个样例中,我们可以选 $X = 3$。

在第一个样例中,我们可以选 $X = 5$。

Solution

看到异或,很自然想到从高位到低位贪心。如果较高的位置是能设为 $0$ 的,那一定将它设为 $0$,这样的答案一定最优。

我们可以对数集建 01-trie,为了适应从高位到低位的贪心,我们将第一层(也就是根节点所在的那一层)的 $dep$ 设为 $30$,从上到下依次 $-1$,得到一个总深度为 $30$ 的 trie,$dep = i$ 的层表示的是 $i$ 位的数字,位数从 $0$ 开始计算,最高到 $29$ 位,可以满足题目中 $a_i \le 2^{30}$ 的要求。

比如样例,有三个数 $1, 2, 3$,我们的 01-trie 是这个样子的:

$\bullet$ 插入 $1$:

$\bullet$ 插入 $2$:

$\bullet$ 插入 $3$:

插入的代码不难写出:

void insert(LL rt, LL val, LL dep)
{
	o[rt].dep = dep;
	if(!dep) return;
	if(!o[rt].ch[val >> dep - 1 & 1]) o[rt].ch[val >> dep - 1 & 1] = ++siz;
	insert(o[rt].ch[val >> dep - 1 & 1], val, dep - 1);
}

然后就可以在 01-trie 上 DP,在每个结点维护一个 $res$,表示以它为根的树的答案。比如现在要求 $res_{rt}$ 根据树形 DP 的基本操作,当然是先递归它的儿子,然后分类讨论一下:

  $\bullet$ 如果 $rt$ 只有一个儿子,那么如果是 $ch_0$,$X$ 的这位就设成 $0$(保持不变),否则就设为 $1$(取反),总有办法使得这个位置的答案是 $0$,所以直接返回该儿子的 $res$ 即可

  $\bullet$ 如果 $rt$ 两个儿子都有,那么如果 $X$ 这位设成 $0$,$ch_1$ 的该位就依然是 $1$;如果设为 $1$,$ch_0$ 的该位就变成了 $1$,既然 $2^{dep_{rt} - 1}$($-1$ 因为是儿子那位的答案,写成 $2 ^{dep_{son}}$ 也行)逃不掉了,在此基础上加上 $\min(res_{ch_0}, res_{ch_1})$ 再返回即可

DP 的代码:

void solve(LL rt)
{
	if(o[rt].ch[0]) solve(o[rt].ch[0]);
	if(o[rt].ch[1]) solve(o[rt].ch[1]);
	if(o[rt].ch[0] && o[rt].ch[1])
		o[rt].res = min(o[o[rt].ch[0]].res, o[o[rt].ch[1]].res) + (1LL << o[rt].dep - 1);
	else o[rt].res = o[o[rt].ch[0]].res + o[o[rt].ch[1]].res;
}

最后根节点 $1$ 的 $res$ 就是答案,完整的代码给出,供参考。

#include <bits/stdc++.h>
#define ROOT 1
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
struct node
{
	LL res, dep, ch[2];
	node() { res = dep = ch[0] = ch[1] = 0; }
} o[N * 20];
LL a[N], n, siz = 1;
void insert(LL rt, LL val, LL dep)
{
	o[rt].dep = dep;
	if(!dep) return;
	if(!o[rt].ch[val >> dep - 1 & 1]) o[rt].ch[val >> dep - 1 & 1] = ++siz;
	insert(o[rt].ch[val >> dep - 1 & 1], val, dep - 1);
}
void solve(LL rt)
{
	if(o[rt].ch[0]) solve(o[rt].ch[0]);
	if(o[rt].ch[1]) solve(o[rt].ch[1]);
	if(o[rt].ch[0] && o[rt].ch[1])
		o[rt].res = min(o[o[rt].ch[0]].res, o[o[rt].ch[1]].res) + (1LL << o[rt].dep - 1);
	else o[rt].res = o[o[rt].ch[0]].res + o[o[rt].ch[1]].res;
}
int main()
{
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
		insert(ROOT, a[i], 30);
	}
	solve(ROOT);
	cout << o[ROOT].res << endl;
	return 0;
}

原文地址:https://www.cnblogs.com/syksykCCC/p/CF285D.html

时间: 2024-08-30 10:36:14

CodeForces 1285D Dr. Evil Underscores的相关文章

Codeforces 1285D Dr. Evil Underscores(字典树,dp)

传送门 题意: 有一个长度为 \(n\ (1\leq n\leq 10^5)\)的整数序列 \(a_1,\cdots,a_n\ \ (0\leq a_i\leq 2^{30}-1)\),你需要找到一个非负整数 \(X\) 使得 \(\max(a_i\oplus X)\)最小,其中 \(\oplus\) 为按位异或运算. 输入这个序列,输出\(\max(a_i\oplus X)\)的最小值. 思路: 1.数组中的每个数的二进制下的某位(第k位)都是0或者是1,那么x的第k位取值是0或者1,使得答案

Dr. Evil Underscores

D - Dr. Evil Underscores 参考:Codeforces Round #613 (Div. 2) Editorial 其实比赛的时候就已经想到了基本上一样的解法,可是最后还是没有写出来... 具体思路就是分治,在二进制中,如果\(a_1{\sim}a_n\),在该位上既有1又有0,说明这一位上的数是躲不掉的,那么这一位上肯定是1,所以在返回的数里加一个1<<i,而对于后面的数则取最小值即可min(dfs(i-1, v0), dfs(i-1, v1))+(1 <<

Codeforces Round #613 (Div. 2) D. Dr. Evil Underscores

题目:http://codeforces.com/contest/1285/problem/D 思路:从高位往低位建 \(01\;trie\) 树,从高位 dfs 当只有一个分支,当前位为 \(0\),填法唯一: 当有两个分支,当前位为 \(1\),填法不唯一,则返回较小值: #include<bits/stdc++.h> using namespace std; const int N=1e5+5; int n; int trie[N*31][2]; int cnt; void insert

Codeforces Round #613 (Div. 2) D - Dr. Evil Underscores(思维,位运算)

?? ?? ?? 题意:对于一个数组,求一个数字与数组每个元素异或之后的最大值最小,求这个最大值 又是位运算,,题目给出数组元素范围在2^30以内,二进制最多30位,从最高位开始贪心,如果此位置的数组元素有的是1有的是0,最后肯定取1,否则取0,还有就是分组讨论,因为每个bit位只能满足原数组中一部分元素异或后为1 #define int ll vector<int>a; int solve(vector<int>v,int bit) { if(bit<=0||v.size(

CF1285D Dr. Evil Underscores

挂个链接 Description: 给你 \(n\) 个数 \(a_1,a_2,--,a_n\) ,让你找出一个 \(x\) ,使 \(x\) 分别异或每一个数后得到的 \(n\) 个结果的最大值最小. Solution: 设 \(x\) 为题中所说, \(m\) 为 \(max{x^a_i}\) : 构建 \(01Trie\) ,将所有数的二进制形式存到 \(01Trie\) 上,对于第 \(k\) 位,存在两种情况: 一是都是0或都是1,这样只要使 \(x\) 的第 \(k\) 位为1或0,

Codeforces Gym 100463D Evil DFS

Evil Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Description Richard is evil. He wants to give another geometry problem to the participants of this contest and I’m afraid I have no choice but to comply. W

Codeforces 526G Spiders Evil Plan

由于做的时候看的是中文题面,第一遍写就被卡题意了:还以为每一条都要过x,那么就是一道动态树根选择2y个叶子的奇怪题目 交完0分gg,才发现题目看错了╮(╯▽╰)╭ the node containing the candy is adjacent to at least one rope covered with a web 完全就是两道题啊..... 首先考虑没有x的做法 贪心显然是对的 1.直径一定要取,否则一定可以通过把与直径最接近(以直径一段为根的lca深度最大)的一条路径改为直径来改善

E - Mahmoud and Ehab and the bipartiteness CodeForces - 862B (dfs黑白染色)

Mahmoud and Ehab continue their adventures! As everybody in the evil land knows, Dr. Evil likes bipartite graphs, especially trees. A tree is a connected acyclic graph. A bipartite graph is a graph, whose vertices can be partitioned into 2 sets in su

CF 862C Mahmoud and Ehab and the xor(异或)

题目链接:http://codeforces.com/problemset/problem/862/C 题目: Mahmoud and Ehab are on the third stage of their adventures now. As you know, Dr. Evil likes sets. This time he won't show them any set from his large collection, but will ask them to create a n