zoukankan      html  css  js  c++  java
  • 最大异或对

    最大异或对

    给出n个数,第i个数为(a_i),问从中任意取两个数,进行异或运算,得到的结果的最大值,(nleq 10^5)

    首先暴力的思路是枚举每一个数,再确定另外一个数,现在问题是如何快速确定另外一个数。

    二进制运算问题,采用二进制拆分,对每一位,尤其是从最高位考虑,尽可能选择一堆数,让最高位不为0,在从选出的一堆数再选一堆数,让次高位尽可能不为0,不停地缩小集合范围,就能得到我们的答案.

    于是问题变成如何快速检索每一位对应的集合,这样我们就可以利用trie树来做了,因为它可以查询某一位一个字符对应的字符串,于是我们把数字看成01串,加入trie树,按照上面所说的思路即可,时间复杂度(O(nlog(n)))

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define Size 3100000
    using namespace std;
    int trie[Size][2],tot,
    	a[100005];
    il int ask(int);
    il void insert(int),
    	read(int&);
    template<class free>
    il free Max(free,free);
    int main(){
    	int n,ans(0);read(n);
    	for(int i(1);i<=n;++i)
    		read(a[i]),insert(a[i]);
    	for(int i(1);i<=n;++i)
    		ans=Max(ans,ask(a[i]));
    	printf("%d",ans);
    	return 0;
    }
    template<class free>
    il free Max(free a,free b){
    	return a>b?a:b;
    }
    il void read(int &x){
    	x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
    	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    il int ask(int x){int p(0),ans(0);
    	for(int i(30);i>=0;--i)
    		if(trie[p][x>>i&1^1])
    			p=trie[p][x>>i&1^1],ans|=1<<i;
    		else p=trie[p][x>>i&1];
    	return ans;
    }
    il void insert(int x){int p(0);
    	for(int i(30);i>=0;--i){
    		if(!trie[p][x>>i&1])
    			trie[p][x>>i&1]=++tot;
    		p=trie[p][x>>i&1];
    	}
    }
    
    
  • 相关阅读:
    uva 11488
    探测器-旅行者1号:百科
    理论-生命起源理论:百科
    定律:目录
    定律:百科
    理论:目录
    理论(哲学):百科
    理论:百科
    汉语-词语:潮汐
    物理-电磁-电磁相互作用:百科
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11248058.html
Copyright © 2011-2022 走看看