Statement

在给定的 个整数 ​中选出两个进行 运算,得到的结果最大是多少?

Solution

建立 0-1 Trie。

0-1 Trie 是一类特殊的字典树,之所以特殊,在于其的字符集为

由于二进制中数码也只有 ,所以 0-1 Trie 上的一条路径可以看做一个数的二进制位。

考虑如何在 0-1 Trie 上求异或最大值。

假定我们已经确定了第一个数为 的某一位为 ,那么我们在 Trie 树上就要尽可能往 走,反之亦然。

因此,我们每读入一个数,先查询,后插入即可。

Code

#include<bits/stdc++.h>
using namespace std;

template < typename Tp >
inline void read(Tp &x) {
    x = 0; int fh = 1; char ch = 1;
    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if(ch == '-') fh = -1, ch = getchar();
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    x *= fh;
}

template < typename Tp >
inline void biread(Tp &x) {
    x = 0; int fh = 1; char ch = 1;
    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if(ch == '-') fh = -1, ch = getchar();
    while(ch >= '0' && ch <= '9') x = x * 2 + ch - '0', ch = getchar();
    x *= fh;
}

int ch[5000000][2], cnt = 1;

inline void insert(int x) {
    int p = 1;
    for(int i = 30; i >= 0; i--) {
        int q = ((x >> i) & 1);
        if(!ch[p][q]) ch[p][q] = ++cnt;
        p = ch[p][q];
    }
}

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

int n, ans;

inline void Init(void) {
    read(n);
    for(int i = 1, x; i <= n; i++) {
        read(x); ans = max(ans, query(x));
        insert(x);
    }
    printf("%d\n", ans);
}

inline void Work(void) {

}

signed main(void) {
    Init();
    Work();
    return 0;
}