three arrays(字典树)

http://acm.hdu.edu.cn/showproblem.php?pid=6625

题目描述

There are three integer arrays a,b,c. The lengths of them are all N. You are given the full contents of a and b. And the elements in c is produced by following equation: c[i]=a[i] XOR b[i] where XOR is the bitwise exclusive or operation.

Now you can rearrange the order of elements in arrays a and b independently before generating the array c. We ask you to produce the lexicographically smallest possible array c after reordering a and b. Please output the resulting array c.

 

输入

The first line contains an integer T indicating there are T tests.

Each test consists of three lines. The first line contains one positive integer N denoting the length of arrays a,b,c. The second line describes the array a. The third line describes the array b.

* T≤1000
* 1≤N≤10^5
* integers in arrays a and b are in the range of [0,2^30).
* at most 6 tests with N>100

 

输出

For each test, output a line containing N integers, representing the lexicographically smallest resulting array c.

 

样例输入

复制样例数据

1
3
3 2 1
4 5 6

样例输出

4 4 7

建两棵字典树进行匹配,尽量走节点值相同的节点(同为0异为1,要使异或值相同,那就尽可能使同一位置上的数相同)

鑫爷tql

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e6;
const int maxc=2;
char s[66];
struct TRIE{
	int Next[maxn][maxc];
	int num[maxn];
	//bool isw[maxn];//查询整个单词用 
	int root=1;
	int tot=0;
	int base;
	void init(){
		for(int i=0;i<=tot;i++) {
			memset(Next[i],0,sizeof(Next[i]));
			num[i]=0;
			//isw[i]=false;
		}
		tot=1;
	}
	void add(char s[],int now){
		int len=strlen(s);
		for(int i=0;i<len;i++){
			int c=s[i]-base;
			if(!Next[now][c]){
			 Next[now][c]=++tot;
			} 
			now=Next[now][c];
		}
		//isw[now]=true;//标记该单词末位字母的尾节点 
	}
	bool find(char s[],int now){
		int len=strlen(s);
		for(int i=0;i<len;i++){
			int c=s[i]-base;
			if(!Next[now][c]) return false;
			now=Next[now][c];
		}
		return true;
		//查询整个单词时,应该return isw[now] 
	}
	void addnum(int x,int now){
		int p[35];
		for(int i=0;i<30;i++){
			p[i]=x&1;
			x>>=1;
		}
		for(int i=29;i>=0;i--){
			int c=p[i];
			if(!Next[now][c]){
				Next[now][c]=++tot;
			}
			now=Next[now][c];
			num[now]++;
		}
		//isw[now]=true;
	}
}a,b;
int q[maxn];
void solve(int pos){//匹配两棵字典树 
	int ra=1,rb=1;
	int ans=0;
	for(int i=29;i>=0;i--){
		int a0=a.Next[ra][0],a1=a.Next[ra][1];
		int b0=b.Next[rb][0],b1=b.Next[rb][1];
		if(a0&&b0&&a.num[a0]&&b.num[b0]) {
			a.num[a0]--;
			b.num[b0]--;
			ra=a0;
			rb=b0;
			continue;
		}
		else if(a1&&b1&&a.num[a1]&&b.num[b1]) {
			a.num[a1]--;
			b.num[b1]--;
			ra=a1;
			rb=b1;
			continue;
		}
		else if(a0&&b1&&a.num[a0]&&b.num[b1]){
			a.num[a0]--;
			b.num[b1]--;
			ra=a0;
			rb=b1;
			ans+=(1<<i);
			continue;
		}
		else if(a1&&b0&&a.num[a1]&&b.num[b0]){
			a.num[a1]--;
			b.num[b0]--;
			ra=a1;
			rb=b0;
			ans+=(1<<i);
			continue;
		}
	}
	q[pos]=ans;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
    	int n;
    	scanf("%d",&n);
    	a.init();
    	for(int i=1;i<=n;i++){
    		int x;
    		scanf("%d",&x);
    		a.addnum(x,1);
		}
		b.init();
    	for(int i=1;i<=n;i++){
    		int x;
    		scanf("%d",&x);
    		b.addnum(x,1);
		}
		for(int i=1;i<=n;i++) solve(i);
		sort(q+1,q+1+n);
		for(int i=1;i<=n;i++)printf("%d%c",q[i]," \n"[i==n]);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值