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题号

HDU6625 three arrays

简单题意

给出长度为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;
}