hdu6625 three arrays (01字典树)

丶灬走出姿态 提交于 2019-11-29 08:20:17

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

题意:

给两个长度为n的数组a,b
告诉你c(i)=a(i)^b(i)
现在要你重新排列a,b数组,
要求c数组的字典序最小
输出c数组的每个元素值

分析:

不必真的重新排列a、b数组
只要能求出c数组就行了

为两个数组建立两棵01字典树
对于每个i,从两颗树的树顶开始跑,
优先走数值相同的路径(0,0或者1,1)
如果没有就只能走不同的(0,1或者1,0)
就能得到一个值c(i)

求出所有c的值之后排序一下保证字典序最小然后输出即可

具体看代码

如果用memset初始化会tle

ps:
好题啊,学到了新的代码格式,新的初始化方法,trie的新操作

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxm=1e5+5;
struct Trie{
    int a[maxm*30][2],tot;
    int cnt[maxm*30];
    void init(){
        for(int i=1;i<tot;i++){//只把用过的清零
            a[i][0]=a[i][1]=0;
            cnt[i]=0;
        }
        tot=1;
    }
    void add(int x){
        int node=0;
        for(int i=30;i>=0;i--){
            int v=(x>>i&1);
            if(!a[node][v]){
                a[node][v]=tot++;
            }
            node=a[node][v];
            cnt[node]++;//路径经过的次数
        }
    }
}a,b;
int c[maxm];
int ask(){
    int ans=0;
    int pa=0,pb=0;
    for(int i=30;i>=0;i--){
        if(a.cnt[a.a[pa][0]]&&b.cnt[b.a[pb][0]]){//0,0
            a.cnt[a.a[pa][0]]--;
            b.cnt[b.a[pb][0]]--;
            pa=a.a[pa][0];
            pb=b.a[pb][0];
        }else if(a.cnt[a.a[pa][1]]&&b.cnt[b.a[pb][1]]){//1,1
            a.cnt[a.a[pa][1]]--;
            b.cnt[b.a[pb][1]]--;
            pa=a.a[pa][1];
            pb=b.a[pb][1];
        }else if(a.cnt[a.a[pa][0]]&&b.cnt[b.a[pb][1]]){//0,1
            a.cnt[a.a[pa][0]]--;
            b.cnt[b.a[pb][1]]--;
            pa=a.a[pa][0];
            pb=b.a[pb][1];
            ans+=(1<<i);
        }else if(a.cnt[a.a[pa][1]]&&b.cnt[b.a[pb][0]]){//1,0
            a.cnt[a.a[pa][1]]--;
            b.cnt[b.a[pb][0]]--;
            pa=a.a[pa][1];
            pb=b.a[pb][0];
            ans+=(1<<i);
        }
    }
    return ans;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        a.init();//reset
        b.init();//reset
        int n;
        scanf("%d",&n);
        for(int i=1,x;i<=n;i++){
            scanf("%d",&x);
            a.add(x);
        }
        for(int i=1,x;i<=n;i++){
            scanf("%d",&x);
            b.add(x);
        }
        for(int i=1;i<=n;i++){
            c[i]=ask();
        }
        sort(c+1,c+1+n);
        for(int i=1;i<n;i++){
            printf("%d ",c[i]);
        }
        printf("%d\n",c[n]);
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!