Trie - Dr. Evil Underscores - CodeForces - 1285D
题意:
给 定 一 个 长 度 为 n 的 序 列 a 1 , a 2 , . . . , a n , 选 择 一 个 整 数 X , 使 得 max i = 1 n ( a i ⊕ X ) 的 值 最 小 , 并 输 出 这 个 最 小 值 。 给定一个长度为n的序列a_1,a_2,...,a_n,选择一个整数X,使得\max_{i=1}^{n}(a_i⊕X)的值最小,并输出这个最小值。 给定一个长度为n的序列a1,a2,...,an,选择一个整数X,使得maxi=1n(ai⊕X)的值最小,并输出这个最小值。
E x a m p l e s : Examples: Examples:
Input:
3
1 2 3
Output:
2
Input:
2
1 5
Output:
4
Note:
In the first sample, we can choose X=3.
In the second sample, we can choose X=5.
数据范围:
n ∈ [ 1 , 100000 ] , a i ∈ [ 0 , 2 30 − 1 ] 。 T i m e l i m i t : 1000 m s , M e m o r y l i m i t : 262144 k B n∈[1,100000],a_i∈[0,2^{30}-1]。\\Time \ limit:1000 ms,Memory\ limit:262144 kB n∈[1,100000],ai∈[0,230−1]。Time limit:1000ms,Memory limit:262144kB
题解:
① 、 对 n 个 整 数 a 以 长 度 为 30 ( 因 为 a 最 大 取 2 30 − 1 ) 的 二 进 制 码 的 形 式 建 立 T r i e 。 ② 、 接 着 爆 搜 最 终 的 答 案 。 若 T r i e 树 上 的 节 点 的 ′ 0 ′ 孩 子 缺 失 , 则 搜 索 其 ′ 1 ′ 孩 子 ; 若 ′ 1 ′ 孩 子 缺 失 , 则 搜 索 其 ′ 0 ′ 孩 子 ; 若 均 未 缺 失 , 则 选 择 计 算 结 果 更 小 的 孩 子 的 值 。 ①、对n个整数a以长度为30(因为a最大取2^{30}-1)的二进制码的形式建立Trie。\\②、接着爆搜最终的答案。\\\qquad若Trie树上的节点的'0'孩子缺失,则搜索其'1'孩子;若'1'孩子缺失,则搜索其'0'孩子;\\\qquad若均未缺失,则选择计算结果更小的孩子的值。 ①、对n个整数a以长度为30(因为a最大取230−1)的二进制码的形式建立Trie。②、接着爆搜最终的答案。若Trie树上的节点的′0′孩子缺失,则搜索其′1′孩子;若′1′孩子缺失,则搜索其′0′孩子;若均未缺失,则选择计算结果更小的孩子的值。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1e5+10,M=30*N;
int son[M][2],n,idx,a;
void Insert(int x)
{
int p=0;
for(int i=29;i>=0;i--)
{
int u=x>>i&1;
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
}
}
int dfs(int p,int k)
{
if(k==-1) return 0;
if(son[p][0]==0) return dfs(son[p][1],k-1);
else if(son[p][1]==0) return dfs(son[p][0],k-1);
else return (1<<k) + min(dfs(son[p][1],k-1),dfs(son[p][0],k-1));
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a);
Insert(a);
}
int ans=dfs(0,29);
printf("%d\n",ans);
return 0;
}