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();
}

 

 

 

posted @ 2019-08-26 17:11  uid001  阅读(139)  评论(0编辑  收藏  举报