题目:http://acm.hdu.edu.cn/showproblem.php?pid=6687
题意:两个数组两两配对使得异或总和最大。
思路:建两颗字典树,按路径不同贪心跑即可。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e5+5;
struct Tree{
int tr[32*maxn][2], cnt;
int ed[32*maxn];
void Insert(int x){
int p = 0, v;
for(int i=31; i>=0; i--){
v = (x>>i)&1;
if(!tr[p][v]) tr[p][v] = ++cnt, tr[cnt][0] = tr[cnt][1] = ed[cnt] = 0;
p = tr[p][v]; ed[p] ++;
}
}
}tree1, tree2;
int Find(){
int p1=0, p2=0, x=0;
for(int i=31; i>=0; i--){
int nxt10 = tree1.tr[p1][0], nxt11 = tree1.tr[p1][1];
int nxt20 = tree2.tr[p2][0], nxt21 = tree2.tr[p2][1];
if(tree1.ed[nxt10] && tree2.ed[nxt21]){
p1 = nxt10;
tree1.ed[p1] --;
p2 = nxt21;
tree2.ed[p2] --;
x += (1<<i);
}else if(tree1.ed[nxt11] && tree2.ed[nxt20]){
p1 = nxt11;
tree1.ed[p1] --;
p2 = nxt20;
tree2.ed[p2] --;
x += (1<<i);
}else if(tree1.ed[nxt10] && tree2.ed[nxt20]){
p1 = nxt10;
tree1.ed[p1] --;
p2 = nxt20;
tree2.ed[p2] --;
}else {
p1 = nxt11;
tree1.ed[p1] --;
p2 = nxt21;
tree2.ed[p2] --;
}
}
return x;
}
int t, n, x; LL ans;
int main()
{
scanf("%d", &t);
while(t--){
tree1.cnt = tree2.cnt = 0; ans = 0;
tree1.tr[0][0] = tree1.tr[0][1] = tree1.ed[0] = 0;
tree2.tr[0][0] = tree2.tr[0][1] = tree2.ed[0] = 0;
scanf("%d", &n);
for(int i=1; i<=n; i++) scanf("%d", &x), tree1.Insert(x);
for(int i=1; i<=n; i++) scanf("%d", &x), tree2.Insert(x);
for(int i=1; i<=n; i++) ans += (LL)Find();
printf("%lld\n", ans);
}
}