题意:给定两个等长数组a,b,你可以随意排列他们,使得数组c字典序最小,其中c[i]=a[i] xor b[i]。
思路:题解的做法貌似很复杂,但在直接建两棵01Trie,在01Trie上贪心的做法也能通过。
public class Main {
public static void main(String[] args) throws IOException {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
InputReader sc = new InputReader(inputStream);
PrintWriter out = new PrintWriter(outputStream);
long s=System.currentTimeMillis();
Task solver = new Task();
solver.solve(1, sc, out);
long e=System.currentTimeMillis();
// System.out.println(e-s);
out.close();
}
static class Task {
public static final int Max=(int) (1e5+10);
public ZeroOneTrie t1;
public ZeroOneTrie t2;
public ArrayList<Integer> get(int n){
ArrayList<Integer> buf=new ArrayList<Integer>();
while(n-->0) {
int res=0;
int index1=0;
int index2=0;
for(int i=30;i>=0;i--) {
if(t1.cnt[t1.next[index1][0]]>0&&t2.cnt[t2.next[index2][0]]>0) {
t1.cnt[t1.next[index1][0]]--;
t2.cnt[t2.next[index2][0]]--;
index1=t1.next[index1][0];
index2=t2.next[index2][0];
}
else
if(t1.cnt[t1.next[index1][1]]>0&&t2.cnt[t2.next[index2][1]]>0) {
t1.cnt[t1.next[index1][1]]--;
t2.cnt[t2.next[index2][1]]--;
index1=t1.next[index1][1];
index2=t2.next[index2][1];
}
else
if(t1.cnt[t1.next[index1][0]]>0&&t2.cnt[t2.next[index2][1]]>0) {
res|=1<<i;
t1.cnt[t1.next[index1][0]]--;
t2.cnt[t2.next[index2][1]]--;
index1=t1.next[index1][0];
index2=t2.next[index2][1];
}
else {
res|=1<<i;
t1.cnt[t1.next[index1][1]]--;
t2.cnt[t2.next[index2][0]]--;
index1=t1.next[index1][1];
index2=t2.next[index2][0];
}
}
buf.add(res);
}
return buf;
}
public void solve(int testNumber, InputReader sc, PrintWriter out) throws IOException {
int T=sc.nextInt();
int[] a=new int[Max];
int[] b=new int[Max];
t1=new ZeroOneTrie(Max);
t2=new ZeroOneTrie(Max);
long s=System.currentTimeMillis();
while(T-->0) {
t1.init();
t2.init();
int n=sc.nextInt();
for(int i=1;i<=n;i++) {
a[i]=sc.nextInt();
t1.insert(a[i]);
}
for(int i=1;i<=n;i++) {
b[i]=sc.nextInt();
t2.insert(b[i]);
}
//long e=System.currentTimeMillis();
// System.out.println((e-s)+"ms");
ArrayList<Integer> res=get(n);
Collections.sort(res);
out.print(res.get(0));
for(int i=1;i<res.size();i++)
out.print(" "+res.get(i));
out.println();
// e=System.currentTimeMillis();
//System.out.println((e-s)+"ms");
}
/* long e=System.currentTimeMillis();
System.out.println((e-s)+"ms");*/
}
}
static class ZeroOneTrie{
public int tot;
public int[][] next;
public int n;
// public int[] val;
public int[] cnt;
public ZeroOneTrie(int n) {
this.n=n;
this.tot=0;
this.next=new int[(n+10)<<5][2];
// this.val=new int[(n+10)<<5];
this.cnt=new int[(n+10)<<5];
}
public void init() {
this.tot=0;
cnt[next[0][0]]=cnt[next[0][1]]=0;
next[0][0]=next[0][1]=0;
}
public void insert(int x) {
int index=0;
for(int i=30;i>=0;i--){
int to=(x>>i)&1;
if(next[index][to]==0){
next[index][to]=++tot;
cnt[next[tot][0]]=cnt[next[tot][1]]=0;
next[tot][0]=next[tot][1]=0; //把将指向的下一个节点初始化
// val[tot]=0;
cnt[tot]=0;
}
index=next[index][to];
cnt[index]++;
}
// val[index]=x;
}
public int ask(int x,int k) { //从当前插入的所有数字中返回与x异或值第k小的一个数
int index=0;
int res=0;
for(int i=30;i>=0;i--) {
int to=(x>>i)&1;
if(k>cnt[next[index][to]]) {
k-=cnt[next[index][to]];
res|=1<<i;
index=next[index][to^1];
}
else
index=next[index][to];
}
return res;
}
/* public int ask(int x) { //从当前插入的所有数字中返回与x异或值最大的一个数
int index=0;
for(int i=30;i>=0;i--) {
int to=(x>>i)&1;
if(next[index][to^1]!=0&&cnt[next[index][to^1]]>0)
index=next[index][to^1];
else
index=next[index][to];
}
return val[index];
}*/
public void del(int x) {
int index=0;
for(int i=30;i>=0;i--) {
int to=(x>>i)&1;
index=next[index][to];
cnt[index]--;
}
}
}
static class InputReader{
StreamTokenizer tokenizer;
public InputReader(InputStream stream){
tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
tokenizer.ordinaryChars(33,126);
tokenizer.wordChars(33,126);
}
public String next() throws IOException {
tokenizer.nextToken();
return tokenizer.sval;
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public boolean hasNext() throws IOException {
int res=tokenizer.nextToken();
tokenizer.pushBack();
return res!=tokenizer.TT_EOF;
}
public double nextDouble() throws NumberFormatException, IOException {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() throws IOException {
return new BigInteger(next());
}
}
}