three arrays HDU - 6625 (字典树)

three arrays

\[Time Limit: 2500 ms \quad Memory Limit: 262144 kB \]

题意

给出 \(a\)\(b\) 数组,定义数组 \(c[i] = a[i] XOR b[i]\),现在可以任意调整 \(a\)\(b\) 的顺序,使得最后的 \(c\) 字典序最小。

思路

对于 \(a\) 数组和 \(b\) 数组分别建立字典树,然后从大到小在字典树上贪心构造尽量小的 \(c\)
对于某一位,如果两颗树上同时有 \(00\) 或者 \(11\),那么就选择往这样的边 \(dfs\),否则的话往 \(01\) 或者 \(10\)\(dfs\),并加上这一位的异或值。
因为 \(01\)\(10\) 不可能同时出现,因为如果同时出现了,肯定优先去 \(00\) 或者 \(11\)。那么就是 \(00\)\(11\) 的情况,可能出现往 \(00\) 的答案是 \(4\),往 \(11\) 的答案是 \(3\),那么无法让小的先出来,所以可以任一选一个走,把另一个留到后面走,然后对于所有求出来的 \(c\)\(sort\) 一遍。

/*************************************************************** 
    > File Name    : a.cpp
    > Author       : Jiaaaaaaaqi
    > Created Time : Fri 06 Sep 2019 09:17:26 PM CST
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int tot[2];
int a[maxn], b[maxn], c[maxn];
int node[2][maxn*30][2], cnt[2][maxn*30];

void insert(int x, int id) {
	int rt = 0;
	for(int i=30; i>=1; i--) {
		int f = (x&(1<<(i-1))) ? 1 : 0;
		if(node[id][rt][f] == 0) {
			tot[id]++;
			mes(node[id][tot[id]], 0);
			cnt[id][tot[id]] = 0;
			node[id][rt][f] = tot[id];
		}
		rt = node[id][rt][f];
		cnt[id][rt]++;
	}
}

int dfs(int rt1, int rt2, int p) {
	// printf("rt1=%d rt2=%d\n", rt1, rt2);
	if(p == 0)	return 0;
	bool ok00 = (node[0][rt1][0] && cnt[0][node[0][rt1][0]]);
	bool ok01 = (node[0][rt1][1] && cnt[0][node[0][rt1][1]]);
	bool ok10 = (node[1][rt2][0] && cnt[1][node[1][rt2][0]]);
	bool ok11 = (node[1][rt2][1] && cnt[1][node[1][rt2][1]]);
	if(ok00 && ok10) {
		cnt[0][node[0][rt1][0]]--, cnt[1][node[1][rt2][0]]--;
		return dfs(node[0][rt1][0], node[1][rt2][0], p-1);
	} else if(ok01 && ok11) {
		cnt[0][node[0][rt1][1]]--, cnt[1][node[1][rt2][1]]--;
		return dfs(node[0][rt1][1], node[1][rt2][1], p-1);
	} else if(ok00 && ok11) {
		cnt[0][node[0][rt1][0]]--, cnt[1][node[1][rt2][1]]--;
		return dfs(node[0][rt1][0], node[1][rt2][1], p-1) + (1<<(p-1));
	} else {
		cnt[0][node[0][rt1][1]]--, cnt[1][node[1][rt2][0]]--;
		return dfs(node[0][rt1][1], node[1][rt2][0], p-1) + (1<<(p-1));
	}
}

int main() {
	// freopen("in", "r", stdin);
	scanf("%d", &T);
	while(T--) {
		cnt[0][0] = cnt[1][0] = tot[0] = tot[1] = 0;
		mes(node[0][0], 0), mes(node[1][0], 0);
		scanf("%d", &n);
		for(int i=1; i<=n; i++)	scanf("%d", &a[i]), insert(a[i], 0);
		for(int i=1; i<=n; i++)	scanf("%d", &b[i]), insert(b[i], 1);
		for(int i=1; i<=n; i++)	c[i] = dfs(0, 0, 30);
		sort(c+1, c+1+n);
		for(int i=1; i<=n; i++)	printf("%d%c", c[i], i==n ? '\n' : ' ');
	}
	return 0;
}
posted @ 2019-09-06 22:17  Jiaaaaaaaqi  阅读(156)  评论(0编辑  收藏  举报