大意: 给两个数组$a,b$, 要求重排使得$c_i=a_ioplus b_i$字典序最小.
字典树上贪心取$n$次, 然后排序, 还不知道怎么证.
#include <iostream> #include <sstream> #include <algorithm> #include <cstdio> #include <cmath> #include <set> #include <map> #include <queue> #include <string> #include <cstring> #include <bitset> #include <functional> #include <random> #define REP(i,a,n) for(int i=a;i<=n;++i) #define PER(i,a,n) for(int i=n;i>=a;--i) #define hr putchar(10) #define pb push_back #define lc (o<<1) #define rc (lc|1) #define mid ((l+r)>>1) #define ls lc,l,mid #define rs rc,mid+1,r #define x first #define y second #define io std::ios::sync_with_stdio(false) #define endl ' ' using namespace std; const int N = 1e5+50, S = 29; int n, T[2], tot; struct {int ch[2];} tr[N*60]; int cnt[N*60][2]; vector<int> ans; void add(int &o, int d, int x, int tp, int v) { if (!o) o=++tot; cnt[o][tp]+=v; if (d>=0) add(tr[o].ch[x>>d&1],d-1,x,tp,v); } void solve(int u, int v, int d, int x, int y) { --cnt[u][0],--cnt[v][1]; if (d<0) return ans.pb(x^y); int A=cnt[tr[u].ch[0]][0],B=cnt[tr[u].ch[1]][0]; int C=cnt[tr[v].ch[0]][1],D=cnt[tr[v].ch[1]][1]; if (A&&C) return solve(tr[u].ch[0],tr[v].ch[0],d-1,x,y); if (B&&D) return solve(tr[u].ch[1],tr[v].ch[1],d-1,x^1<<d,y^1<<d); if (A&&D) return solve(tr[u].ch[0],tr[v].ch[1],d-1,x,y^1<<d); if (B&&C) return solve(tr[u].ch[1],tr[v].ch[0],d-1,x^1<<d,y); } void work() { scanf("%d", &n); REP(z,0,1) REP(i,1,n) { int t; scanf("%d", &t); add(T[z],S,t,z,1); } ans.clear(); REP(i,1,n) solve(T[0],T[1],S,0,0); sort(begin(ans),end(ans)); REP(i,0,n-1) printf("%d%c",ans[i]," "[i==n-1]); T[0]=T[1]=0; while (tot) cnt[tot][0]=cnt[tot][1]=tr[tot].ch[0]=tr[tot].ch[1]=0,--tot; } int main() { int t; scanf("%d", &t); while (t--) work(); }