zoukankan      html  css  js  c++  java
  • # [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;
    }
    
  • 相关阅读:
    好好活,做有意义的事
    linux运维、架构之路-linux基础知识
    linux运维、架构之路-linux目录结构
    linux运维、架构之路-linux基础优化
    linux运维、架构之路-SSH远程管理服务
    linux运维、架构之路-实时同步方案
    linux运维、架构之路-nfs网络文件系统
    linux运维、架构之路-全网备份项目方案
    linux运维、架构之路-rsync
    编程题
  • 原文地址:https://www.cnblogs.com/sstealer/p/12233116.html
Copyright © 2011-2022 走看看