hdu 6625 three array (01-trie)
大意: 给两个数组$a,b$, 要求重排使得$c_i=a_i\oplus 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 '\n'
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]," \n"[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();
}

浙公网安备 33010602011771号