three arrays HDU - 6625 (字典树)

Posted jiaaaaaaaqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

以上是关于three arrays HDU - 6625 (字典树)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6625 three arrays 求两个序列异或最小值的排列(一个可以推广的正解

双01字典树最小XOR(three arrays)--2019 Multi-University Training Contest 5(hdu杭电多校第5场)

HDU 5878 I Count Two Three

HDU 5878 I Count Two Three

hdu5340—Three Palindromes—(Manacher算法)——回文子串

HDU - 5340 Three Palindromes(manacher算法)