首页 > 其他 > 详细

求集合中选一个数与当前值进行位运算的max

时间:2018-07-30 10:05:18      阅读:150      评论:0      收藏:0      [点我收藏+]

求集合中选一个数与当前值进行位运算的max

这是一个听来的神仙东西。
先确定一下值域把,大概\(2^{16}\),再大点也可以,但是这里就只是写写,所以无所谓啦。

我们先看看如果暴力求怎么做,位运算需要给定\(01/10,00,11\)的关系,总共\(8\)种。
如果是暴力的话,我们的方法有两种,
第一种是比较喜闻乐见的,
我们对于当前数\(x\),暴力计算所有存在的数\(a_i\)中,\(x\oplus a_i\)的最大值,这样的复杂度是\(O(2^{16})\)的。
另外一种也是不难考虑到的,
我们对于每个可能出现的数维护一个当前所有数的最大值。
也就是对于所有值域中的数,维护一个答案\(ans\)
然后依次插入所有集合中所有的数\(a_i\),每次暴力计算所有的答案的最大值,
也就是\(ans[x]=max\{x\oplus a_i \}\),这样子询问的时候可以\(O(1)\)查询。

两种方法一种是插入\(O(1)\)询问\(O(n)\),另外一个是插入\(O(n)\),询问\(O(1)\)
我们把两种东西结合一下,这样可以得到一个\(O(\sqrt n)\)的方法。
大致的方法如下:
我们对于每个数从中间分开,拆成前\(8\)个二进制位和后\(8\)个二进制位。
这样子我们可以预处理一个数组\(pre[i][j]\)
表示集合中一个前\(8\)位是\(i\)的数,后\(8\)位能够和\(j\)进行位运算的最大值。
这样子\(i,j\)都是一个\(8\)位的数,总的空间和上述方法一样。
因为位运算是可以按位贪心的,所以对于查询一个数\(x\)
我们把它拆成\(x=a\times 2^8+b\)
每次先暴力\(for\)所有可能的前\(8\)位,找到与\(a\)能够构成最大值的那些数,
然后对于找到的所有数的前八位\(p\),直接查\(pre[p][b]\)
因为前八位更大的数一定更大,那么影响结果的就只剩下后八位了,
把两个部分拼接起来就好了。
这样子暴力\(for\)前八位的复杂度是\(O(2^8)\)
查找后面部分最大值的复杂度是\(O(1)\)
所以这样子总的复杂度\(O(2^8)\)
而对于集合中插入一个数,前\(8\)位唯一确定,每次只需要预处理后\(8\)位的结果。
时间复杂度还是\(O(2^8)\)
总的复杂度还是\(O(2^8)\)

求集合中选一个数与当前值进行位运算的max

原文:https://www.cnblogs.com/cjyyb/p/9388651.html

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