题目链接&&题目大意
http://codeforces.com/contest/923/problem/C
For given and , find the lexicographically smallest message , for which there exists a permutation such that XOR = for every i.
对给定序列 和 ,找 的一个排列 ,使 XOR = 得到的序列 字典序最小。
解题思路
贪心,每次找与 做XOR运算结果最小的 ,即可保证序列 字典序最小。
将序列 的每个元素 从高位到低位插到01字典树中。
对序列 的每个元素 ,从高位到低位,每一步都尝试沿着与 的当前位相同的指针向下访问,若指向空结点,则访问与 当前位相反的指针。根据XOR运算相同得0,不同得1的性质,即可找到与 做XOR运算结果最小的 。
为满足一一对应XOR的要求,需额外维护每个结点的存储次数 ,每次访问后 - -,用后即删。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define RPD(i, b, a) for (int i = (b), i##_end_ = (a); i >= i##_end_; --i)
typedef long long LL;
const int oo = 0x3f3f3f3f;
const int MAXN = 300010;
inline int read()
{
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9'){x = x * 10 + (c - '0'); c = getchar();}
return x * f;
}
int trie[MAXN * 30][2], cnt[MAXN * 30][2], val[MAXN * 30], tot;
int n, a[MAXN];
void add(int x)
{
int cur = 0;
RPD(i, 29, 0){
int y = (x >> i) & 1;
if(!trie[cur][y]) trie[cur][y] = ++ tot;
cnt[cur][y] ++;
cur = trie[cur][y];
}
val[cur] = x;
}
int ask(int x)
{
int cur = 0;
RPD(i, 29, 0){
int y = (x >> i) & 1;
if(cnt[cur][y]){
cnt[cur][y] --;
cur = trie[cur][y];
}
else{
cnt[cur][y ^ 1] --;
cur = trie[cur][y ^ 1];
}
}
return val[cur];
}
int main()
{
n = read();
REP(i, 1, n) a[i] = read();
REP(i, 1, n){
int num = read();
add(num);
}
REP(i, 1, n) cout << (a[i] ^ ask(a[i])) << ' ';
return 0;
}