码迷,mamicode.com
首页 > Windows程序 > 详细

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

时间:2020-01-25 16:45:10      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:存在   cpp   mem   query   include   can   ++i   inline   code   

[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] 最大异或和 [字典树]

标签:存在   cpp   mem   query   include   can   ++i   inline   code   

原文地址:https://www.cnblogs.com/sstealer/p/12233116.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!