这道题的贪心想法是这样的,我们希望产生的最小值越多越好,那么如果对于当前的某一位,同时走 1 或者同时 走 0 的匹配一定比 一个走1,一个走 0 的 要小,那么一直执行这样一个递归的过程,我们就可以得到最小的值。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 20000001;
vector<LL> ve;
struct T{
int tot = 0,ch[maxn][2],cnt[maxn];
LL val[maxn];
void init(){
for( int i =0;i <= tot;i++ ){
ch[i][0] = ch[i][1] = cnt[i] = 0;
}
tot = 0;
}
void insrt( int x,int d,LL v ){
if( d == -1 ){
val[x] = v;
cnt[x]++;
return;
}
int dir = v>>d&1;
if(!ch[x][dir]) ch[x][dir] = ++tot;
insrt( ch[x][dir],d-1,v );
cnt[x] = (ch[x][0]?cnt[ ch[x][0] ]:0) + (ch[x][1]?cnt[ ch[x][1] ]:0);
}
}g1,g2;
void solve( int x,int y ){
if( !g1.ch[x][0]&&!g1.ch[x][1] ){
int mn = min( g1.cnt[x],g2.cnt[y] );
for( int i = 1;i <= mn;i++ )ve.push_back( g1.val[ x ]^g2.val[y] );
g1.cnt[x] -=mn; g2.cnt[y] -=mn ;
return;
}
if( g1.cnt[ g1.ch[x][0] ]&& g1.ch[x][0] &&g2.cnt[g2.ch[y][0] ] && g2.ch[y][0] ){
solve( g1.ch[x][0],g2.ch[y][0] );
}
if( g1.cnt[ g1.ch[x][1] ]&&g1.ch[x][1] &&g2.cnt[g2.ch[y][1] ]&& g2.ch[y][1] ){
solve( g1.ch[x][1],g2.ch[y][1] );
}
if( g1.ch[x][0]&&g1.cnt[ g1.ch[x][0] ] && g2.ch[y][1]&&g2.cnt[ g2.ch[y][1] ] ){
solve( g1.ch[x][0],g2.ch[y][1] );
}
if( g1.ch[x][1]&&g1.cnt[ g1.ch[x][1] ] && g2.ch[y][0]&&g2.cnt[ g2.ch[y][0] ] ){
solve( g1.ch[x][1],g2.ch[y][0] );
}
g1.cnt[x] = (g1.ch[x][0]?g1.cnt[ g1.ch[x][0] ]:0) + (g1.ch[x][1]?g1.cnt[ g1.ch[x][1] ]:0);
g2.cnt[y] = (g2.ch[y][0]?g2.cnt[ g2.ch[y][0] ]:0) + (g2.ch[y][1]?g2.cnt[ g2.ch[y][1] ]:0);
}
LL a[maxn],b[maxn];
int main(){
int T,n;
scanf("%d",&T);
while(T--){
ve.clear();g1.init();g2.init();
scanf("%d",&n);
for( int i = 1;i <= n;i++ ){
scanf("%lld",&a[i]);
g1.insrt( 0,30,a[i] );
}
for( int i = 1;i <= n;i++ ) {
scanf("%lld",&b[i]);
g2.insrt( 0,30,b[i] );
}
solve( 0,0 );
sort( ve.begin(),ve.end() );
printf("%lld",ve[0]);
for( int i =1; i < ve.size();i++ ){
printf(" %lld",ve[i]);
}
printf("\n");
}
return 0;
}