three arrays HDU - 6625 (字典树)

three arrays

\[ Time Limit: 2500 ms \quad Memory Limit: 262144 kB \]

题意

给出 \(a\)\(b\) 数组,定义数组 \(c[i] = a[i] XOR b[i]\),现在可以任意调整 \(a\)\(b\) 的顺序,使得最后的 \(c\) 字典序最小。

思路

对于 \(a\) 数组和 \(b\) 数组分别建立字典树,然后从大到小在字典树上贪心构造尽量小的 \(c\)
对于某一位,如果两颗树上同时有 \(00\) 或者 \(11\),那么就选择往这样的边 \(dfs\),否则的话往 \(01\) 或者 \(10\)\(dfs\),并加上这一位的异或值。
因为 \(01\)\(10\) 不可能同时出现,因为如果同时出现了,肯定优先去 \(00\) 或者 \(11\)。那么就是 \(00\)\(11\) 的情况,可能出现往 \(00\) 的答案是 \(4\),往 \(11\) 的答案是 \(3\),那么无法让小的先出来,所以可以任一选一个走,把另一个留到后面走,然后对于所有求出来的 \(c\)\(sort\) 一遍。

/*************************************************************** 
    > File Name    : a.cpp
    > Author       : Jiaaaaaaaqi
    > Created Time : Fri 06 Sep 2019 09:17:26 PM CST
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int tot[2];
int a[maxn], b[maxn], c[maxn];
int node[2][maxn*30][2], cnt[2][maxn*30];

void insert(int x, int id) {
    int rt = 0;
    for(int i=30; i>=1; i--) {
        int f = (x&(1<<(i-1))) ? 1 : 0;
        if(node[id][rt][f] == 0) {
            tot[id]++;
            mes(node[id][tot[id]], 0);
            cnt[id][tot[id]] = 0;
            node[id][rt][f] = tot[id];
        }
        rt = node[id][rt][f];
        cnt[id][rt]++;
    }
}

int dfs(int rt1, int rt2, int p) {
    // printf("rt1=%d rt2=%d\n", rt1, rt2);
    if(p == 0)  return 0;
    bool ok00 = (node[0][rt1][0] && cnt[0][node[0][rt1][0]]);
    bool ok01 = (node[0][rt1][1] && cnt[0][node[0][rt1][1]]);
    bool ok10 = (node[1][rt2][0] && cnt[1][node[1][rt2][0]]);
    bool ok11 = (node[1][rt2][1] && cnt[1][node[1][rt2][1]]);
    if(ok00 && ok10) {
        cnt[0][node[0][rt1][0]]--, cnt[1][node[1][rt2][0]]--;
        return dfs(node[0][rt1][0], node[1][rt2][0], p-1);
    } else if(ok01 && ok11) {
        cnt[0][node[0][rt1][1]]--, cnt[1][node[1][rt2][1]]--;
        return dfs(node[0][rt1][1], node[1][rt2][1], p-1);
    } else if(ok00 && ok11) {
        cnt[0][node[0][rt1][0]]--, cnt[1][node[1][rt2][1]]--;
        return dfs(node[0][rt1][0], node[1][rt2][1], p-1) + (1<<(p-1));
    } else {
        cnt[0][node[0][rt1][1]]--, cnt[1][node[1][rt2][0]]--;
        return dfs(node[0][rt1][1], node[1][rt2][0], p-1) + (1<<(p-1));
    }
}

int main() {
    // freopen("in", "r", stdin);
    scanf("%d", &T);
    while(T--) {
        cnt[0][0] = cnt[1][0] = tot[0] = tot[1] = 0;
        mes(node[0][0], 0), mes(node[1][0], 0);
        scanf("%d", &n);
        for(int i=1; i<=n; i++) scanf("%d", &a[i]), insert(a[i], 0);
        for(int i=1; i<=n; i++) scanf("%d", &b[i]), insert(b[i], 1);
        for(int i=1; i<=n; i++) c[i] = dfs(0, 0, 30);
        sort(c+1, c+1+n);
        for(int i=1; i<=n; i++) printf("%d%c", c[i], i==n ? '\n' : ' ');
    }
    return 0;
}

转载于:https://www.cnblogs.com/Jiaaaaaaaqi/p/11478595.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值