【01字典树+贪心】HDU 6625 three arrays (2019杭电多校第五场)

three arrays

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

 

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数组为a数组和b数组异或出来的,字典序最小,输出c数组

解法:A,B数组分别建字典树,贪心的思考,只要这一位都有0或都有1,那就最好,不行就走01或10,答案+(1<<i)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node
{
    int ch[2],val;
}a[2][32*maxn];
int tot[2];
int ans[maxn];
void Insert(int x,int op)
{
    int u=0;
    for(int i=30;i>=0;i--)
    {
        int v=(x>>i)&1;
        if(!a[op][u].ch[v])
        {
            a[op][u].ch[v]=++tot[op];
            a[op][tot[op]].ch[0]=a[op][tot[op]].ch[1]=a[op][tot[op]].val=0;
        }
        u=a[op][u].ch[v];
        a[op][u].val++;
    }
}

void init()
{
    tot[0]=tot[1]=0;
    a[0][0].ch[0]=a[0][0].ch[1]=a[1][0].ch[0]=a[1][0].ch[1]=0;
    a[0][0].val=a[1][0].val;
}

int query()
{
    int x=0;
    int p=0,q=0;
    for(int i=30;i>=0;i--)
    {
        if(a[0][a[0][p].ch[0]].val&&a[1][a[1][q].ch[0]].val)
        {
            p=a[0][p].ch[0],q=a[1][q].ch[0];
            a[0][p].val--,a[1][q].val--;
        }
        else if(a[0][a[0][p].ch[1]].val&&a[1][a[1][q].ch[1]].val)
        {
            p=a[0][p].ch[1],q=a[1][q].ch[1];
            a[0][p].val--,a[1][q].val--;
        }
        else if(a[0][a[0][p].ch[0]].val&&a[1][a[1][q].ch[1]].val)
        {
            p=a[0][p].ch[0],q=a[1][q].ch[1];
            a[0][p].val--,a[1][q].val--;
            x+=(1<<i);
        }
        else
        {
            p=a[0][p].ch[1],q=a[1][q].ch[0];
            a[0][p].val--,a[1][q].val--;
            x+=(1<<i);
        }
    }
    return x;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();

        int n,x;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,0);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            Insert(x,1);
        }

        for(int i=1;i<=n;i++)
            ans[i]=query();
        sort(ans+1,ans+n+1);
        for(int i=1;i<=n;i++)
        {
            printf("%d%c",ans[i],i==n?'\n':' ');
        }
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值