# [AcWing143] 最大异或和 [字典树]

Posted sstealer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# [AcWing143] 最大异或和 [字典树]相关的知识,希望对你有一定的参考价值。

[AcWing143] 最大异或和 [字典树]

传送门

题意

给出N个整数,选择两个整数,使得异或和最大((0<A_i<2^{31})

思路

从数据范围很容易想到二进制,进而想到字典树Trie。

字典树的典型应用是存储字符串,存储二进制也是一样的。

我一开始在处理取二进制位的时候想的比较麻烦,我是使用右移运算符先预处理出每个数的二进制表示,再根据二进制表示插入字典树中。后来了解到x >> i & 1;可以直接取二进制数的任意一位,这样简单了许多。

查询的时候,先取出对应位的二进制数,在树中先走该二进制数的对立面,如果对立面不存在,再沿着该二进制数向下走一层。

Code:

#include <bits/stdc++.h>
using namespace std;
#define fre freopen("data.in","r",stdin);
#define ms(a) memset((a),0,sizeof(a))
#define go(i,a,b) for(register int (i)=(a);(i)<(b);++(i))
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);++(i))
#define sf(x) scanf("%d",&(x))
#define reg register
typedef long long LL;
const int inf=(0x3f3f3f3f);
const int maxn=1e5+5;
int a[maxn],son[maxn*31][2],idx;
int n;
inline void insert(int x){
    int p=0,t;
    for(int i=30;i>=0;i--){
        t= x >> i & 1; //取二进制数的第i位,从0开始
        if(!son[p][t])son[p][t]=++idx;
        p=son[p][t];
    }
}
inline int query(int x){
    int ans=0,t,p=0;
    for(int i=30;i>=0;--i){
        t=x>>i&1;
        if(son[p][!t]){
            p=son[p][!t];
            ans|=(1<<i);
        }
        else {
            p=son[p][t];
        }
    }
    return ans;
}
int main(){
    sf(n);
    rep(i,1,n){
        sf(a[i]);
        insert(a[i]);
    }
    int mx=-1;
    rep(i,1,n){
        mx=max(mx,query(a[i]));
    }
    printf("%d",mx);
    return 0;
}

以上是关于# [AcWing143] 最大异或和 [字典树]的主要内容,如果未能解决你的问题,请参考以下文章

AcWing 143 最大异或对

bzoj3261: 最大异或和 可持久化字典树模板

AcWing 143. 最大异或对

AcWing 143. 最大异或对

AcWing 143. 最大异或对

AcWing 143. 最大异或对