好题收集(3)

来源:互联网 发布:淘宝没有销售属性 编辑:程序博客网 时间:2024/05/24 01:51

异或最大值

Description

异或最大值
n个非负数 (int范围) 中任意2个的异或值的最大值(n1e5)

Hint

我们注意到n2肯定过不了,所以要用更好的方法
每个数最多231,只有31位,想到转化成O(31n)可以过,也就是说我们要分位处理
运用trie树,把每个数都补齐成31位,然后存在trie树里,我们分解一个数时,如果一位是1,就向0方向找,反之就向1方向找,这里是贪心的思想

注:如果是与和或就不能用这种方法,我们以与为例,如果一位为1,你可以向1的方向找,但如果这位是0,你向0向1都有可能,如果你都去找时间和暴力就差不多了,所以不能用这种方法

Code

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<cmath>#define siz 100100using namespace std;int n,pos;long long ans,numa,numb;long long a[siz];struct Node {    int l,r,num;}node[siz*31];  //开到n*最大位数void insert(long long x) {    int k,u=0;    for(int i=31;i>=0;--i) {        k=(x&(1<<i));        if(k) {            if(!node[u].r) node[u].r=++pos;            u=node[u].r;        } else {            if(!node[u].l) node[u].l=++pos;            u=node[u].l;        }    }    node[u].num=x;}void qwq(long long x) {    int k,u=0;    for(int i=31;i>=0;--i) {        k=(x&(1<<i));        if(k) {            if(node[u].l) u=node[u].l;            else u=node[u].r;        } else {            if(node[u].r) u=node[u].r;            else u=node[u].l;        }    }    if((x^node[u].num)>ans)         ans=(x^node[u].num),numa=x,numb=node[u].num;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i) {        scanf("%lld",&a[i]);        insert(a[i]);        qwq(a[i]);    }    printf("%lld %lld %lld",ans,numa,numb);    return 0;}}