2019 Multi-University Training Contest 5 three arrays (01字典树)

three arrays

Time Limit: 3000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2175    Accepted Submission(s): 754


 

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:  6730 6729 6728 6727 6726 

 题目大意:两个数组a,b b数组可以重新排序,c数组是有ai^bi 得到的,求如何排列是c的字典序最小。

解题思路:比赛时想到了字典树,直接把b排序了,然后对于每一个b在a中找最小。然而这样是不对的。

正解应该是 建立两颗01字典树,我们尽量走 (0,0) (1,1)因为这样才能使得贡献最小,否则的话就只能

走(0,1) (1,0)。然后将取出来的数字排序就可以了。

#include<bits/stdc++.h>
using namespace std;
#define sca(x) scanf("%d",&x)
#define LL long long
#define pb(x) push_back(x)

const int N  = 1e5+5;

struct node
{
    int nt[2];
    int sz[2];
}t[N*40][2];

int a[N],b[N];
int c[N];

int root;
int tot1,tot2;

void init( )
{

    for(int i=0;i<max(tot1,tot2);i++)
    {
        t[i][0].nt[0]=t[i][0].nt[1]=0;
        t[i][0].sz[0]=t[i][0].sz[1]=0;
        t[i][1].nt[0]=t[i][1].nt[1]=0;
        t[i][1].sz[0]=t[i][1].sz[1]=0;
    }
}

int _newnode(int ty)
{
    if(ty==0)tot1++;
    else tot2++;
    int tot=(ty==0?tot1:tot2);
    t[tot][ty].nt[0]=t[tot][ty].nt[1]=0;
    t[tot][ty].sz[0]=t[tot][ty].sz[1]=0;
    return tot;
}

void _ins(int k,int ty)
{
    int now=root;
    for(int i=30;i>=0;i--){
        int id=(k>>i)&1;
        if(t[now][ty].nt[id]==0){
            t[now][ty].nt[id] = _newnode(ty);
        }
        t[now][ty].sz[id]++;
        now=t[now][ty].nt[id];
    }
}


int _ask( )
{
    int le=0,ri=0;
    int res=0;
    for(int i=30;i>=0;i--)
    {
        int s10=t[le][0].sz[0],s11=t[le][0].sz[1];
        int s20=t[ri][1].sz[0],s21=t[ri][1].sz[1];
        if(s10 && s20)
        {
            t[le][0].sz[0]--;
            t[ri][1].sz[0]--;
            le=t[le][0].nt[0];
            ri=t[ri][1].nt[0];
            continue;
        }
        if(s11 && s21)
        {
            t[le][0].sz[1]--;
            t[ri][1].sz[1]--;
            le=t[le][0].nt[1];
            ri=t[ri][1].nt[1];
            continue;
        }
        if(s10 && s21)
        {
            t[le][0].sz[0]--;
            t[ri][1].sz[1]--;
            res|= (1<<i);
            le=t[le][0].nt[0];
            ri=t[ri][1].nt[1];
            continue;
        }
        if(s11 && s20 )
        {
            t[le][0].sz[1]--;
            t[ri][1].sz[0]--;
            res|=(1<<i);
            le=t[le][0].nt[1];
            ri=t[ri][1].nt[0];
            continue;
        }
    }
    return res;
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        tot1=tot2=0;
        root=0;
        int n;
        sca(n);
        for(int i=1;i<=n;i++){
            sca(a[i]);
        }
        for(int i=1;i<=n;i++){
            sca(b[i]);
        }

        for(int i=1;i<=n;i++){
            _ins(a[i],0);
            _ins(b[i],1);
        }

        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]);
            if(i==n)printf("\n");
            else printf(" ");
        }
        init( );
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值