codeforces 1285D. Dr. Evil Underscores(字典树)
链接:https://codeforces.com/problemset/problem/1285/D
题意:给n个数a1,a2,a3.....an,找到一个数X,使得X 异或所有的ai ,得到的max(X xor ai)最小,输出这个值。
思路:a的范围是0~230,我们可以以01二进制的形式建一棵深度为30的字典树,每个数ai 的二进制序列插入到字典树中去,例如5 = 101,那么101按位插入到字典树中去。然后从根开始遍历,在字典树上dp,因为该字典树建完后是一棵二叉树,所以分支情况就两种,下一位是0或1,那么如果只遇到1就往1这个分支走,这一位便没有贡献,如果只遇到0就往0这个分支走,这一位也没有贡献,如果遇到的是0和1两个分支,那么必定要加上这一位的贡献,然后递归01两个分支,两者再去min,一直递归到最后一位。
AC代码:
1 #include<iostream> 2 #include<vector> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 #include<cstring> 8 #include<queue> 9 #include<map> 10 using namespace std; 11 typedef long long ll; 12 int trie[6000005][2],cnt ; 13 //bool exist[31*31];// 该结点结尾的字符串是否存在 14 void insert(int a){//建trie树 15 int p = 0; 16 for(int i = 29;i>=0;i--){ 17 int c = (a>>i)&1; 18 if(!trie[p][c]) trie[p][c] = ++cnt; // 如果没有,就添加结点 19 p = trie[p][c]; 20 } 21 // exist[p] = 1; 22 } 23 ll solve(ll cur,int k){ 24 if(k == -1) return 0; 25 if(trie[cur][0] == 0){ 26 return solve(trie[cur][1],k-1); 27 } 28 else if(trie[cur][1] == 0){ 29 return solve(trie[cur][0],k-1); 30 } 31 else{ 32 return (1<<k)+min(solve(trie[cur][0],k-1),solve(trie[cur][1],k-1)); 33 } 34 } 35 int main() 36 { 37 int n; 38 cin>>n; 39 for(int i = 0;i<n;i++){ 40 ll a;cin>>a; 41 insert(a); 42 } 43 ll ans = solve(0,29); 44 cout<<ans; 45 return 0; 46 }