最大异或对

最大异或对

给出n个数,第i个数为\(a_i\),问从中任意取两个数,进行异或运算,得到的结果的最大值,\(n\leq 10^5\)

首先暴力的思路是枚举每一个数,再确定另外一个数,现在问题是如何快速确定另外一个数。

二进制运算问题,采用二进制拆分,对每一位,尤其是从最高位考虑,尽可能选择一堆数,让最高位不为0,在从选出的一堆数再选一堆数,让次高位尽可能不为0,不停地缩小集合范围,就能得到我们的答案.

于是问题变成如何快速检索每一位对应的集合,这样我们就可以利用trie树来做了,因为它可以查询某一位一个字符对应的字符串,于是我们把数字看成01串,加入trie树,按照上面所说的思路即可,时间复杂度\(O(nlog(n))\)

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define Size 3100000
using namespace std;
int trie[Size][2],tot,
    a[100005];
il int ask(int);
il void insert(int),
    read(int&);
template<class free>
il free Max(free,free);
int main(){
    int n,ans(0);read(n);
    for(int i(1);i<=n;++i)
        read(a[i]),insert(a[i]);
    for(int i(1);i<=n;++i)
        ans=Max(ans,ask(a[i]));
    printf("%d",ans);
    return 0;
}
template<class free>
il free Max(free a,free b){
    return a>b?a:b;
}
il void read(int &x){
    x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
il int ask(int x){int p(0),ans(0);
    for(int i(30);i>=0;--i)
        if(trie[p][x>>i&1^1])
            p=trie[p][x>>i&1^1],ans|=1<<i;
        else p=trie[p][x>>i&1];
    return ans;
}
il void insert(int x){int p(0);
    for(int i(30);i>=0;--i){
        if(!trie[p][x>>i&1])
            trie[p][x>>i&1]=++tot;
        p=trie[p][x>>i&1];
    }
}

猜你喜欢

转载自www.cnblogs.com/a1b3c7d9/p/11248058.html