First unscrupulous propaganda about the blog wwwwww
Article list - nuclear fusion reactor core - Luo Gubo off
Knowledge Point: Trie tree / tree dictionary / greedy
Meaning of the questions:
(Abridged version of casual working too Kichiku a)
There \ (a, b \) two of length \ (n-\) is the number of columns,
the \ (B \) series rearrange,
then \ (a, b \) corresponding to the position number of phases \ (\ underline {\ XOR text {}} \) ,
to give a new series \ (C \)
You can find a new series \ (C \) \ (\ underline {\ lexicographically smallest text {}} \) scheme
, and outputs the result of this program
\(1\leqslant N \leqslant 3e5\)
\(\underline{a[i],b[i] \leqslant 2^{30}}\)
Analysis of the meaning of problems:
Lexicographically smallest:
the \ (C \) each position of the number of columns \ (C [I] \) ,
should be able to reach the minimum value
can be considered greedyXOR, \ (A [I], B [I] \ leqslant 2 ^ {30} \) :
? Why the data range to be written like this
consider ... XOR operation
occur binary splitThe \ (a [i], b [i] \) after the split, greedy can easily
enumerate two \ (01 \) number on the strings every
try to make different or after you as \ ( 0 \)
to select the most appropriate \ (b [i] \)What used to maintain binary number after the split?
Binary numbers can be
treated as a string to handle
expect to establish a dictionary tree
because only \ (0 \) two characters, it is a binary tree
based on the nature of the dictionary tree,
you can completion of the operation easily.
Algorithm:
Based on the respective first establish a \ (b [i] \) of the binary trie
and record the number of elements in each node represents occurring \ (CNT \)Each query operation, the \ (a [i] \) for the parameters passed
from the dictionary root portion, start looking down,
to find each layer (i.e., each bit) elements,
as much as possible so that \ (a [i ], b [i] \) this bit is XORed \ (0 \)
if the number of this element in the optimum position \ (0 \) , select another element
number of the selected element so that this position \ (--1 \)
and go to the next level and continue to find it.Depending on the nature of the dictionary tree,
each query operations are necessarily can be found,
a local optimum to meet the most suitable \ (a [i] \) a \ (b [i] \)
Query \ (\ n-) after the time, i.e., You can find the best answerNote specific point:
To facilitate the operation,
to ensure that the dictionary tree,
binary numbers stored in the forwardThat is,
if using bitwise binary split
first upper split out, and then split the low
Refer to code
attach Ugly Code:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#define int long long
//==================================================
const int MARX = 3e5+10;
struct node
{
int cnt,son[2];//存每个节点代表元素出现次数 , 两儿子
}trie[20*MARX];
int n,num=1;
int a[MARX],b[MARX];//原始数列
//==================================================
inline int read()
{
int fl=1,w=0;char ch=getchar();
while(!isdigit(ch) && ch!='-') ch=getchar();
if(ch=='-') fl=-1;
while(isdigit(ch)){w=w*10+ch-'0',ch=getchar();}
return fl*w;
}
inline void insert(int key)//建树
{
int now=1;//从根节点开始,向下查找
trie[1].cnt++;
for(int i=30;i>=0;i--)//将二进制数正向加入字典树
{
int next=(key>>i)&1; //当前位数
if(!trie[now].son[next]) trie[now].son[next]= ++num;//添加新节点
now=trie[now].son[next];
trie[now].cnt++;//增加出现次数
}
}
inline int query(int key)//回答询问
{
int now=1,ans=0;//从根部查找
for(int i=30;i>=0;i--)
{
int next=(key>>i)&1;//最优情况
if(!trie[trie[now].son[next]].cnt) next=(!next);//不能满足最优情况
ans=(ans<<1)+next;//更新找到的 b[i]
now=trie[now].son[next];
trie[now].cnt--;//减少出现次数
}
return ans^key;
}
//==================================================
signed main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read(),insert(b[i]);
for(int i=1;i<=n;i++) printf("%lld ",query(a[i]));
}