Description
(nle 2 imes 10^5,a_i,b_ile 2^{30})。
Solution
看到异或会很自然的想起 ( ext{trie}),考虑对 (a) 和 (b) 分别建一棵 ( ext{trie}),然后同时 ( ext{dfs}) 往下搜索,因为要让 (c) 最小,因此先走同 0 或 同 1,然后对于没匹配完的部分再走不同。
最后对于求出的 (c) 进行排序就可以保证字典序最小。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200005
using namespace std;
int n,num,a[N],b[N],c[N];
struct node
{
int tot,tree[N*30][2],size[N*30];
bool bj[N*30];
void ins(int x)
{
int now=0;
size[0]++;
for (int i=30;i>=0;--i)
{
int u=x>>i&1;
if (!tree[now][u]) tree[now][u]=++tot;
now=tree[now][u];
size[now]++;
}
bj[now]=true;
}
}trie1,trie2;
int dfs(int x,int y,int sum,int pos)
{
if (!trie1.size[x]||!trie2.size[y]) return 0;
if (pos<0)
{
int s=min(trie1.size[x],trie2.size[y]);
for (int i=1;i<=s;++i)
c[++num]=sum;
trie1.size[x]-=s;trie2.size[y]-=s;
return s;
}
int res=0;
if (trie1.tree[x][0]&&trie2.tree[y][0]) res+=dfs(trie1.tree[x][0],trie2.tree[y][0],sum,pos-1);
if (trie1.tree[x][1]&&trie2.tree[y][1]) res+=dfs(trie1.tree[x][1],trie2.tree[y][1],sum,pos-1);
if (trie1.tree[x][0]&&trie2.tree[y][1]) res+=dfs(trie1.tree[x][0],trie2.tree[y][1],sum+(1<<pos),pos-1);
if (trie1.tree[x][1]&&trie2.tree[y][0]) res+=dfs(trie1.tree[x][1],trie2.tree[y][0],sum+(1<<pos),pos-1);
trie1.size[x]-=res;trie2.size[y]-=res;
return res;
}
int main()
{
freopen("doubt.in","r",stdin);
freopen("doubt.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
for (int i=1;i<=n;++i)
scanf("%d",&b[i]);
for (int i=1;i<=n;++i)
trie1.ins(a[i]);
for (int i=1;i<=n;++i)
trie2.ins(b[i]);
dfs(0,0,0,30);
sort(c+1,c+num+1);
for (int i=1;i<=num;++i)
printf("%d ",c[i]);
return 0;
}