D o u b t Doubt Doubt
最 初 想 法 \color{grey}{最初想法} 最初想法
按顺序构造
c
i
c_i
ci, 每次 贪心 地将
min
(
a
⨁
b
)
\min(a \bigoplus b)
min(a⨁b) 取出, 作为
c
i
c_i
ci, 可以保证字典序最小,
朴素实现是
O
(
N
2
)
O(N^2)
O(N2) 的, 加上用 桶 对第二个测试点 相同的数字加速处理 可以获得
50
p
t
s
50pts
50pts .
考虑直接找每个 a i a_i ai 所匹配的 b i b_i bi, 发现若 a i a_i ai 找了 b i b_i bi, 会影响到后面的 a j a_j aj 找 b i b_i bi, 换句话说, 这样会有后效性 .
正 解 部 分 \color{red}{正解部分} 正解部分
不用关心 a i a_i ai 匹配哪个 b i b_i bi, 只需使得 c c c 的 较小值较小 即可实现 字典序最小,
于是对
a
a
a 和
b
b
b 分别开一个 深度越大, 位数越低 的
0
/
1
T
r
i
e
0/1\ Trie
0/1 Trie树,
从两颗
T
r
i
e
Trie
Trie树 贪心 地从根节点同步向下走, 优先走权值相同的节点, 使得
c
c
c 的 越小值越小 即可 .
实 现 部 分 \color{red}{实现部分} 实现部分
- 根节点的下标赋为 1 1 1, 0 0 0 节点留作 虚点, 用来判边界 .
- T r i e Trie Trie 中的 A d d ( ) Add() Add() 函数, t o to to 要开 b o o l bool bool 类型 .
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 6e6 + 10;
struct Trie{
int rot;
int node_cnt;
struct Node{ int ch[2], cnt; } T[maxn];
void Add(int x){
int cur = rot;
for(reg int i = 30; i >= 0; i --){
bool to = (x & (1 << i));
if(!T[cur].ch[to]) T[cur].ch[to] = ++ node_cnt;
cur = T[cur].ch[to];
T[cur].cnt ++;
}
}
} t_a, t_b;
int c_cnt;
int c[maxn];
void DFS(int k_1, int k_2, int sum, int pw){
if(k_1) t_a.T[k_1].cnt --, t_b.T[k_2].cnt --;
if(pw == 0){ c[++ c_cnt] = sum; return ; }
while(t_a.T[t_a.T[k_1].ch[0]].cnt && t_b.T[t_b.T[k_2].ch[0]].cnt) DFS(t_a.T[k_1].ch[0], t_b.T[k_2].ch[0], sum, pw>>1);
while(t_a.T[t_a.T[k_1].ch[1]].cnt && t_b.T[t_b.T[k_2].ch[1]].cnt) DFS(t_a.T[k_1].ch[1], t_b.T[k_2].ch[1], sum, pw>>1);
while(t_a.T[t_a.T[k_1].ch[1]].cnt && t_b.T[t_b.T[k_2].ch[0]].cnt) DFS(t_a.T[k_1].ch[1], t_b.T[k_2].ch[0], sum|pw, pw>>1);
while(t_a.T[t_a.T[k_1].ch[0]].cnt && t_b.T[t_b.T[k_2].ch[1]].cnt) DFS(t_a.T[k_1].ch[0], t_b.T[k_2].ch[1], sum|pw, pw>>1);
}
int N;
int main(){
N = read();
t_a.rot = t_b.rot = 1;
t_a.node_cnt = t_b.node_cnt = 1;
for(reg int i = 1; i <= N; i ++) t_a.Add(read());
for(reg int i = 1; i <= N; i ++) t_b.Add(read());
DFS(1, 1, 0, 1<<30);
std::sort(c+1, c+c_cnt+1);
for(reg int i = 1; i <= c_cnt; i ++) printf("%d ", c[i]);
return 0;
}