Codeforces 923C Perfect Security(字典树)

题目链接:Perfect Security

题意

有两个长度为 n n 的序列 a1,a2,,an a 1 , a 2 , ⋯ , a n b1,b2,,bn b 1 , b 2 , ⋯ , b n ,对于每一个 ai a i ,在 b b 序列中找到一个数字与其异或,成为新序列的第 i i 个元素 ci c i ,然后从 b b 序列中删去被选中的数字,求能够构成的新序列中字典序最小的序列。

输入

第一行包含一个整数 n (1N3×105) n   ( 1 ≤ N ≤ 3 × 10 5 ) ,第二行为 n n 个整数 a1,a2,,an (0ai<230) a 1 , a 2 , ⋯ , a n   ( 0 ≤ a i < 2 30 ) ,第三行为 n n 个整数 b1,b2,,bn (0bi<230) b 1 , b 2 , ⋯ , b n   ( 0 ≤ b i < 2 30 )

输出

输出 n n 个整数,第 i i 个整数表示所求新序列的第 i i 项。

样例

输入
3
8 4 13
17 2 7
输出
10 3 28
提示
82=10 8 ⨁ 2 = 10 47=3 4 ⨁ 7 = 3 1317=28 13 ⨁ 17 = 28 。对于其他可能的答案: (25,6,10),(25,3,15),(10,21,10),(15,21,15),(15,6,28) ( 25 , 6 , 10 ) , ( 25 , 3 , 15 ) , ( 10 , 21 , 10 ) , ( 15 , 21 , 15 ) , ( 15 , 6 , 28 ) ,都比 (10,3,28) ( 10 , 3 , 28 ) 的字典序大。
输入
5
12 7 87 22 11
18 39 9 12 16
输出
0 14 69 6 44
输入
10
331415699 278745619 998190004 423175621 42983144 166555524 843586353 802130100 337889448 685310951
226011312 266003835 342809544 504667531 529814910 684873393 817026985 844010788 993949858 1031395667
输出
128965467 243912600 4281110 112029883 223689619 76924724 429589 119397893 613490433 362863284

题解

将所有 b b 序列中的数字建一棵字典树,从 1 1 n n 对于每一个 i i ,都取一个 b b 序列中与 ai a i 异或值最小的,然后将这个数字在字典树中出现的次数 1 − 1

过题代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define LL long long
const int maxm = 300000 + 100;
const int maxn = 300000 * 32 + 100;
const int Size = 2;
struct Trie {
    int root, cnt;
    int val[maxn], tree[maxn][Size];

    int creat() {
        ++cnt;
        memset(tree[cnt], 0, sizeof(tree[cnt]));
        val[cnt] = 0;
        return cnt;
    }

    void Init() {
        cnt = 0;
        root = creat();
    }

    int id(int x, int dig) {
        return ((x >> (31 - dig)) & 1);
    }

    void add(int x) {
        int pos = root;
        for(int i = 0; i < 32; ++i) {
            int w = id(x, i);
            if(tree[pos][w] == 0) {
                tree[pos][w] = creat();
            }
            pos = tree[pos][w];
            ++val[pos];
        }
    }

    int query(int x) {
        int ret = 0;
        int pos = root;
        for(int i = 0; i < 32; ++i) {
            int w = id(x, i);
            if(tree[pos][w] == 0 || val[tree[pos][w]] == 0) {
                w = !w;
                ret |= (1 << (31 - i));
            }
            pos = tree[pos][w];
            --val[pos];
        }
        return ret;
    }
};
Trie t;
int n, x;
int num[maxn];

int main() {
    #ifdef LOCAL
        freopen("test.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    #endif // LOCAL
    ios::sync_with_stdio(false);

    while(scanf("%d", &n) != EOF) {
        t.Init();
        for(int i = 0; i < n; ++i) {
            scanf("%d", &num[i]);
        }
        for(int i = 0; i < n; ++i) {
            scanf("%d", &x);
            t.add(x);
        }
        for(int i = 0; i < n; ++i) {
            if(i != 0) {
                printf(" ");
            }
            printf("%d", t.query(num[i]));
        }
        printf("\n");
    }

    return 0;
}

你可能感兴趣的:(字典树)