[CodeForces - 1285D] Dr. Evil Underscores 异或 01Trie树
题目链接:https://codeforces.com/problemset/problem/1285/D
【题目描述】
Today, as a friendship gift, Bakry gave Badawy nn integers a1,a2,…,ana1,a2,…,an and challenged him to choose an integer XX such that the value max1≤i≤n(ai⊕X)max1≤i≤n(ai⊕X) is minimum possible, where ⊕⊕ denotes the bitwise XOR operation.
As always, Badawy is too lazy, so you decided to help him and find the minimum possible value of max1≤i≤n(ai⊕X)max1≤i≤n(ai⊕X).
【题意】:给你一堆数,你可以自己选一个X,使这堆数与X异或后的最大值最小。输出这个最小值
【题解】:从高位到低位看,如果这一位0和1都存在,那答案肯定加这一位。
然后分成这一位是0的集合与这一位是1的集合,看剩下的几位如何最小,对两个结果取min
如果只有0或1存在,那答案这一位为1,直接看下几位。
爆搜的话可以用vector存,这里用01trie存的递归起来很方便。
【AC代码】
1 #include <bits/stdc++.h> 2 using namespace std; 3 int const maxn=4e6; 4 int tr01[maxn][2],x; 5 int len,check[maxn],n,tot; 6 void insert(int x){//01树构建 7 int ex,v=0; 8 for(int i=29;i>=0;i--){ 9 ex=!!(x&(1<<i)); 10 if(tr01[v][ex])v=tr01[v][ex]; 11 else{ 12 tr01[v][ex]=++tot; 13 v=tot; 14 } 15 } 16 } 17 void init(){ 18 tot=0; 19 memset(tr01,0,sizeof(tr01)); 20 } 21 int work(int x,int wei){ 22 /* 23 如果这一位0和1都存在,那答案肯定加这一位。 24 然后分成这一位是0的集合与这一位是1的集合,看剩下的几位如何最小,对两个结果取min 25 如果只有0或1存在,那答案这一位为1,直接看下几位。 26 爆搜的话可以用vector存,这里用01trie存的递归起来很方便。 27 28 */ 29 if(!tr01[x][0]&&!tr01[x][1])return 0; 30 if(tr01[x][0]==0) return work(tr01[x][1],wei-1); 31 if(tr01[x][1]==0) return work(tr01[x][0],wei-1); 32 return (1<<wei)+min(work(tr01[x][1],wei-1),work(tr01[x][0],wei-1)); 33 } 34 int main(){ 35 scanf("%d",&n); 36 init(); 37 for(int i=1;i<=n;i++){ 38 scanf("%d",&x); 39 insert(x); 40 } 41 // cout<<tot<<endl; 42 printf("%d\n",work(0,29)); 43 return 0; 44 }