Codeforces Round #470 D. Perfect Security(字典树)
http://codeforces.com/contest/948/problem/D
题意:给你两个数组A[]、P[](两个数组元素个数一样多),让你求两个数组中Ai异或Pj的最小值(两个数组中的元素只能取一次);
分析:仔细一看其实就是字典树,我们把P[]数组建立成字典树,用A[]数组中的每一位元素去匹配字典树,取最小值。
#include<cstdio> using namespace std; const int MAX=2; const int maxn=3e5+100; int A[maxn]; int tot=0; struct Trie { int l,r;///左边为0,右边为1 int nl,nr;///0的个数和1的个数 }a[32*maxn]; void Insert(int x) { int id=0; for(int i=29; i>=0; i--) { if(x&(1<<i))///x的二进制表示的第i位数为1 { a[id].nr++; if(a[id].r!=-1) id=a[id].r; else { tot++; a[id].r=tot; a[tot].l=-1; a[tot].r=-1; a[tot].nr=0; a[tot].nl=0; id=tot; } } else///第i位为0 { a[id].nl++; if(a[id].l!=-1) id=a[id].l; else { tot++; a[id].l=tot; a[tot].l=-1; a[tot].r=-1; a[tot].nr=0; a[tot].nl=0; id=tot; } } } } int Find(int x) { int id=0; int ans=0; for(int i=29; i>=0; i--) { if(x&(1<<i))///1; { if(a[id].nr!=0) { a[id].nr--; id=a[id].r; } else { a[id].nl--; ans=ans+(1<<i); id=a[id].l; } } else { if(a[id].nl) { a[id].nl--; id=a[id].l; } else { a[id].nr--; ans=ans+(1<<i); id=a[id].r; } } } return ans; } int main() { int N; scanf("%d",&N); a[0].l=a[0].r=-1; a[0].nl=a[0].nr=0; for(int i=1; i<=N; i++) { scanf("%d",&A[i]); } for(int i=1; i<=N; i++) { int x; scanf("%d",&x); Insert(x); } for(int i=1; i<=N; i++) printf("%d ",Find(A[i])); return 0; }