• 0x16 Tire之最大的异或对


    我们考虑所有的二元组(i,j)且i<j,那么本题的目标就是在其中找到Ai xorAj的最大值。也就是说,对于每个i(1≤i≤N),我们希望找到一个j(1<j<i),使AixorAj最大,并求出这个最大值。

    我们可以把每个整数看作长度为32的二进制01串(数值较小时在前边补0),并且把A1~Ai-1对应的32位二进制串插入一棵Trie 树(其中最低二进制位为叶子节点)。接下来,对于Ai对应的32位二进制串,我们在Trie中进行一次与检索类似的过程,每一步都尝试沿着“与Ai的当前位相反的字符指针”向下访问。若与Ai的当前位相反的字符指针”指向空节点,则只好访问与Ai当前位相同的字符指针。根据xor运算“相同得0,不同得1”的性质,该方法即可找出与Ai做xor运算结果最大的Aj。

    如下图所示,在一棵插入了2(010), 5(101), 7111)三个数的Trie中,分别查询与6(110), 3(011)做xor运算结果最大的数。(为了简便, 图中使用了3位二进制数代替32位二进制数)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int SIZE=100010;
    int trie[SIZE*32+5][2], tot = 1; // 初始化,假设字符串由小写字母构成
    int a[SIZE], n, ans;
    
    void insert(int val) { // 插入一个二进制数
        int p = 1;
        for (int k = 30; k >= 0; k--) {
            int ch = val >> k & 1;
            if (trie[p][ch] == 0) trie[p][ch] = ++tot;
            p = trie[p][ch];
        }
    }
    
    int search(int val) {
        int p = 1;
        int ans = 0;
        for (int k = 30; k >= 0; k--) {
            int ch = val >> k & 1;
            if (trie[p][ch ^ 1]) { // 走相反的位
                p = trie[p][ch ^ 1];
                ans |= 1 << k;
            } else { // 只能走相同的位
                p = trie[p][ch];
            }
        }
        return ans;
    }
    
    int main() {
        cin>>n;
        for(int i=1;i<=n;i++) {
            scanf("%d", &a[i]);
            insert(a[i]);
            ans=max(ans, search(a[i]));
        }
        cout<<ans<<endl;
    }
    

      

    加油啦!加油鸭,冲鸭!!!
  • 相关阅读:
    消息机制
    窗口!窗口!- Windows程序设计(SDK)003
    内联函数的作用
    结构体变量用 . 结构体指针用-> 的原因
    &a和a的区别
    分布电容
    介电常数
    天线
    封装的思想
    关于中断标志位
  • 原文地址:https://www.cnblogs.com/clarencezzh/p/10778351.html
Copyright © 2020-2023  润新知