首页 > Windows开发 > 详细

AcWing:143. 最大异或对(01字典树 + 位运算 + 异或性质)

时间:2019-08-05 23:53:44      阅读:167      评论:0      收藏:0      [点我收藏+]

在给定的N个整数A1A2ANA1,A2……AN中选出两个进行xor(异或)运算,得到的结果最大是多少?

输入格式

第一行输入一个整数N。

第二行输入N个整数A1A1~ANAN。

输出格式

输出一个整数表示答案。

数据范围

1N1051≤N≤105,
0Ai<2310≤Ai<231

输入样例:

3
1 2 3

输出样例:

3

 

算法:01字典树 + 位运算 + 异或性质

题解:首先我们并看不出来这个题目需要用到字典树,但是,我们可以发现数据的范围只有31位,那么我们就可以同过这个点来建立关于位数的字典树。首先,我们把每个数的二进制看作一个字符串,然后开始建树...查询的话,就是每次匹配异或1之后的数(假如是1,你就找0,相反,则找1),如果每次找到的是异或之后的数,你就把当前位赋1。

 

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 1e5+7;

int tree[maxn * 30][2];
int tot;

void insert(int x) {
    int root = 0;
    for(int i = 30; i >= 0; i--) {
        int idx = (x >> i) & 1;     //获取每位的值
        if(tree[root][idx] == 0) {
            tree[root][idx] = ++tot;
        }
        root = tree[root][idx];
    }
}

int search(int x) {
    int ans = 0;
    int root = 0;
    for(int i = 30; i >= 0; i--) {
        int idx = (x >> i) & 1;
        if(tree[root][1 ^ idx] != 0) {      
            ans |= (1 << i);    //如果当前位不同,就把当前位赋1
            root = tree[root][1 ^ idx];
        } else {
            root = tree[root][idx];
        }
    }
    return ans;
}

int main() {
    int n;
    scanf("%d", &n);
    int ans = 0;
    for(int i = 1; i <= n; i++) {
        int x;
        scanf("%d", &x);
        insert(x);
        ans = max(ans, search(x));
    }
    printf("%d\n", ans);
    return 0;
}

 

AcWing:143. 最大异或对(01字典树 + 位运算 + 异或性质)

原文:https://www.cnblogs.com/buhuiflydepig/p/11306057.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!