three arrays
Time Limit: 3000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2339 Accepted Submission(s): 798
Problem Description
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.
Input
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≤105
* integers in arrays a and b are in the range of [0,230).
* at most 6 tests with N>100
Output
For each test, output a line containing N integers, representing the lexicographically smallest resulting array c.
Sample Input
1 3 3 2 1 4 5 6
Sample Output
4 4 7
Source
2019 Multi-University Training Contest 5
Recommend
liuyiding | We have carefully selected several similar problems for you: 6742 6741 6740 6739 6738
23.
OJ题号
简单题意
给出长度为n的两个序列a和b,对序列内随意排序,a[i]^b[i]=c[i],这样得到序列c,要求得出字典序最小的序列c。其中1≤n≤1e5,a,b=[0,2^30)
正解思路
要求字典序最小,那么只要贪心地从序列a,b中尽可能把异或值小的匹配全部选出来,然后从小到大排个序就是答案。
这个就可以很好地用01字典树实现了,先把序列a,b分别建成两棵01字典树,然后同时遍历,优先找同为0或同为1的(这样异或就可以尽可能地小),每次遍历完后删除这个值。
#include <bits/stdc++.h>
using namespace std;
#define N 100000+5
typedef long long ll;
ll c[N];
const int maxnode=1500000+100;//预计字典树最大节点数目
const int sigma_size=2; //每个节点的最多儿子数
const int max_base=31;
struct Trie
{
int ch[maxnode][sigma_size];//ch[i][j]==k表示第i个节点的第j个儿子是节点k
int val[maxnode];//val[i]==x表示第i个节点的权值为x
int sum[maxnode];//sum[i]==x表示第i个节点的次数为x,便于删除
int sz;//字典树一共有sz个节点,从0到sz-1标号
//初始化
void clear()
{
sz=1;
ch[0][0]=ch[0][1]=0;
val[0]=0;
sum[0]=0;
// memset(ch[0],0,sizeof(ch[0]));//ch值为0表示没有儿子
// memset(sum,0,sizeof(sum));
}
//在字典树中插入单词s,但是如果已经存在s单词会重复插入且覆盖权值
//所以insert前需要判断一下是否已经存在s单词了
void insert(int num)
{
int u=0;
for(int i=max_base; i>=0; i--) ///建立字典树
{
int id=((num>>i)&1);
if(ch[u][id]==0)//无该儿子
{
ch[u][id]=sz;
memset(ch[sz],0,sizeof(ch[sz]));
val[sz++]=0;
}
u=ch[u][id];
sum[u]++;
}
val[u]=num;
}
//插入的数据x[i]异或num1 < num2 的个数
int find3(int num1,int num2)
{
int u=0;
int ans=0;
for(int i=max_base; i>=0; i--)
{
int t1=((num1>>i)&1);
int t2=((num2>>i)&1);
if(t1)
{
if(t2)
{
if(ch[u][1])
ans+=sum[ch[u][1]];
u=ch[u][0] ;
}
else
{
u=ch[u][1];
}
}
else
{
if(t2)
{
if(ch[u][0])
ans+=sum[ch[u][0]];
u=ch[u][1];
}
else
u=ch[u][0];
}
if(u==0)
break;
}
return ans;
}
//找与x异或的最大值
ll find(ll x)
{
ll ans=0,u=0;
for(int i=max_base; i>=0; i--)
{
int id=(x>>i)&1;
int y=id^1; //找与id不同的
if(ch[u][y]==0)
{
u=ch[u][id];
ans<<=1; //相同为0,ans=ans*2
}
else
{
u=ch[u][y];
ans=ans<<1|1; //不同为1,ans=ans*2+1
}
}
return ans;
}
void del(int num,int cnt)
{
int u=0;
for(int i=max_base; i>=0; i--)
{
int id=((num>>i)&1);
if(ch[u][id]==0)
return ;
u=ch[u][id];
sum[u]-=cnt;
}
}
};
Trie trie[3];
bool check(int u1,int u2,int num1,int num2)
{
if(trie[1].ch[u1][num1]&&trie[2].ch[u2][num2]&&trie[1].sum[trie[1].ch[u1][num1]]&&trie[2].sum[trie[2].ch[u2][num2]])
return 1;
return 0;
}
ll get_min()
{
int u1=0,u2=0;
ll res=0;
for(int i=max_base; i>=0; i--)
{
if(check(u1,u2,0,0))
{
u1=trie[1].ch[u1][0];
u2=trie[2].ch[u2][0];
}
else if(check(u1,u2,1,1))
{
u1=trie[1].ch[u1][1];
u2=trie[2].ch[u2][1];
}
else if(check(u1,u2,0,1))
{
u1=trie[1].ch[u1][0];
u2=trie[2].ch[u2][1];
}
else if(check(u1,u2,1,0))
{
u1=trie[1].ch[u1][1];
u2=trie[2].ch[u2][0];
}
//trie[1].sum[u1]--;
//trie[2].sum[u2]--;
}
trie[1].del(trie[1].val[u1],1);
trie[2].del(trie[2].val[u2],1);
return trie[1].val[u1]^trie[2].val[u2];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
trie[1].clear();
trie[2].clear();
int n;
scanf("%d",&n);
int a,b;
for(int i=1; i<=n; i++)
{
scanf("%d",&a);
trie[1].insert(a);
}
for(int i=1; i<=n; i++)
{
scanf("%d",&b);
trie[2].insert(b);
}
for(int i=1; i<=n; i++)
{
c[i]=get_min();
}
sort(c+1,c+n+1);
for(int i=1; i<n; i++)
{
printf("%lld ",c[i]);
}
printf("%lld\n",c[n]);
}
return 0;
}