最大异或对的求解

题目:
在这里插入图片描述
先想想暴力的做法
在这里插入图片描述
第二重循环我们人为定义为下标比i小的数,是因为a[2] a[5] 和a[5] a[2]是一样的,为了不走回头路。
我们可以优化一下第二重循环,使用Trie优化。第二重循环就是要在选定i的时候,在a[0] ~ a[i] 间选择一个和a[i]异或之后最大的数。
对于一个给定的数,他的每一位上的数都是确定的,那么如果能找出找从高位到低位不相同的数位只要尽可能的多,就能够找到最大值。
在这里插入图片描述
因为最开始的时候集合为空,为了不用进行特判,我们先插入,然后再查询。每一个数有31位,因此设置M= 3100000
代码实现如下:

#include<iostream>
#include<algorithm>

using namespace std;
const int N = 100010, M = 31 * N;

int a[N];
int son[M][2], idx;
int n;

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];
    }
}

int query(int x){
    
    
    int p = 0, res = 0;
    
    for(int i = 30; i >= 0; i--){
    
    
        int u = x >> i & 1;
        if(son[p][!u]) {
    
    
            p = son[p][!u];
            res = res * 2 + !u;
        }
        else {
    
    
            p = son[p][u];
            res = res * 2 + u;
        }
    }
    return res;
}

int main(){
    
    
    cin >> n;
    int res = 0;
    for(int i = 0; i < n; i++) {
    
    
        cin >> a[i];
        insert(a[i]);
        
        int t = query(a[i]);
        
        res = max(res, a[i]^t);
    }
    
    printf("%d\n", res);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44879626/article/details/108037520