【ACWing】143. 最大异或对

题目地址:

https://www.acwing.com/problem/content/description/145/

给定 N N N个整数 A 1 , . . . , A N A_1,...,A_N A1,...,AN,问将两个数进行异或运算能得到的最大值。

输入格式:
第一行输入一个整数 N N N。第二行输入 N N N个整数 A 1 ∼ A N A_1\sim A_N A1AN

输出格式:
输出一个整数表示答案。

数据范围:
1 ≤ N ≤ 1 0 5 1\le N\le 10^5 1N105
0 ≤ A i < 2 31 0\le A_i<2^{31} 0Ai<231

将每个数看成一个 31 31 31位二进制整数,然后对每个数 x x x,从高位到低位的顺序插入一个Trie。接着对 x x x在Trie中从根向下走,每一步尽量走与 x x x当前二进制位不同的那条边。走到底的时候路径所表示的数就是与 x x x异或最大的那个数。当然也可以先查询后插入,不影响答案的正确性(因为自己和自己异或是 0 0 0,这是能取到的最小答案)。代码如下:

#include 
using namespace std;

// Trie的节点数目可以开大一点
const int N = 100010, M = 31 * N;
int a[N], son[M][2], idx;

void insert(int x) {
    int p = 0;
    for (int i = 30; i >= 0; i--) {
        int u = x >> i & 1;
        if (!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
}

// 询问与x异或最大的那个数是几
int query(int x) {
    int res = 0;
    int p = 0;
    for (int i = 30; i >= 0; i--) {
        int u = x >> i & 1;
        // 能走不同的边,就走之,反之只能走相同边
        if (son[p][!u]) {
            p = son[p][!u];
            res |= (!u) << i;
        } else {
            p = son[p][u];
            res |= u << i;
        }
    }

    return res;
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];

    int res = 0;
    for (int i = 0; i < n; i++) {
        insert(a[i]);
        res = max(res, query(a[i]) ^ a[i]);
    }

    cout << res << endl;

    return 0;
}

时空复杂度 O ( N ) O(N) O(N)

你可能感兴趣的:(AC,数据结构,数据结构,算法)