zoukankan      html  css  js  c++  java
  • ☆ [HDU4825] Xor Sum「最大异或和(Trie树)」

    传送门:>Here<

    题意:给出一个集合,包含N个数,每次询问给出一个数x,问x与集合中的一个数y异或得到最大值时,y是多少?

    解题思路

      由于N,M非常大,暴力显然不行。抓住重点是异或,所以可以把数字转换为二进制。这又让我们想到了字典树……

      根据二进制中数的定理:任何一个位置靠前的数比后面所有的数加起来都大。就好像十进制,100比99大。因此异或的时候要尽量让靠前的数与它不一样。

      把集合内的所有数字根据二进制建立字典树。很明显因为是二进制只有0和1,当前的trie一定是一棵二叉树。因此我们可以拿当前数到trie里面跑一遍,因为trie是前缀树,所以先碰到的肯定是二进制前的。如果有不同的路(就是说如果当前数字为0,看有没有通往1的路)就走,否则没办法

      注意到数字最多只有32位。因为要建立前缀树,所以如果数字太小可以补充前导零。每一次用一个bool数组记录一下数字的各个位即可

    Code

      End数组要清零

    /*By DennyQi*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 3300010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar(); return x * w;
    }
    int T,N,M,x;
    int ch[MAXN][2],cnt,End[MAXN];
    bool num[70];
    inline void Convert(int x){
        memset(num, 0, sizeof(num));
        for(int i = 33; x > 0; --i, x>>=1) num[i] = x%2;
    }
    inline void Insert(int x){
        Convert(x);
        int u = 0;
        for(int i = 1; i <= 33; ++i){
            if(!ch[u][num[i]]) ch[u][num[i]] = ++cnt;
            u = ch[u][num[i]];
        }
        End[u] = x;
    }
    inline int Query(int x){
        Convert(x);
        int u = 0, res = 0;
        for(int i = 1; i <= 33; ++i){
            if(!ch[u][!num[i]]) u = ch[u][num[i]];
            else u = ch[u][!num[i]];
            if(End[u]) res = Max(res, End[u]);
        }
        return res;
    }
    inline void Init(){
        cnt = 0;
        memset(ch, 0, sizeof(ch));
        memset(End, 0, sizeof(End));
    }
    int main(){
        T=r;
        for(int _c = 1; _c <= T; ++_c){
            printf("Case #%d:
    ",_c);
            Init();
            N=r,M=r;
            for(int i = 1; i <= N; ++i) x=r, Insert(x);
            for(int i = 1; i <= M; ++i) x=r, printf("%d
    ", Query(x));
        }
        return 0;
    }
  • 相关阅读:
    keepalived+httpd 高可用
    网卡绑定配置文件
    elk安装
    mysql数据库
    sed
    kvm
    日常巡检
    haproxy
    (6)PY_(study)
    (5)PY_(study)
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9425017.html
Copyright © 2011-2022 走看看