题意:
第一行给你一个n
第二行给你n个数字 分别是a[1],a[2].....a[n]。
第三行给你n个数字 分别是b[1],b[2].....b[n]。

问:第三行的序列可自由排列,要求排列之后的顺序 a[1]^b[1],a[2]^b[2]...a[n]^b[n]的字典序最小。

题解:
因为b数组可以自由排列,那么我们把b数组先生成一个字典序。
要想字典序最小,那么根据贪心的思想,我们a[1]要与b中的某个数异或后值最小。
那么我们再遍历一遍a数组每次找出当前能组合的最小值。

因为每次组合后,我们需要删除b中一个元素,那么b已经是字典树了,怎么删?
我们用一个size数组来记录这个数出现的次数,和一个fa数组记录当前结点的父亲结点。
当size[node]=0的时候,这个数字也就没了,就该删除这个结点了。(因为可能会出现重复数组)
递归往上删除,如果当前节点删除,他的父节点只有它一个孩子,那么该父节点也需要删除,重复操作即可!
代码:

/*Keep on going Never give up*/
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>

//#define int long long
#define endl '\n'
#define Accepted 0
#define AK main()
#define I_can signed
using namespace std;
const int maxn =1e7+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
using namespace std;

int trie[maxn][2],sz[maxn],fa[maxn];
int cnt;
int a[500000];

void ins(int x){
    int node=0;
    for(int i=31;i>=0;i--){
        int t=(x>>i)&1;
        if(!trie[node][t]){
            trie[node][t]=++cnt;
            fa[cnt]=node;
        }
        node=trie[node][t];
    }
    sz[node]++;
}

int quer(int x){
    int res=0,node=0;
    for(int i=31;i>=0;i--){
        int t=(x>>i)&1;
        if(trie[node][t]){
            node=trie[node][t];
        }
        else{
            node=trie[node][t^1];
            res|=(1<<i);
        }
    }
    if((--sz[node])==0){
        while(node){
            int f=fa[node],b;

            if(trie[f][1]==node) b=1;
            else b=0;
            trie[f][b] = 0;
            trie[node][b]=0;
            if(trie[f][b^1]) break;
            node=f;
        }
    }
    return res;
}

signed main()
{
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        //ins(a[i]);
    }
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        ins(x);
    }
    for(int i=0;i<n;i++){
        cout<<quer(a[i])<<" ";
    }

    return 0;
}