zoukankan      html  css  js  c++  java
  • 求集合中选一个数与当前值进行位运算的max

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

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

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

  • 相关阅读:
    下拉选择框,允许手动输入和过滤
    MVC数据绑定
    一个页面多个ng-app注意事项
    modal 多层弹窗 Maximum call stack size exceeded 解决方法
    VS10x CodeMap 注册码(key):
    VS2015卸载再安装
    VS2015无法创建工程
    解决VS2015版本key required问题手动方案
    猪猪公寓—事后诸葛亮
    猪猪公寓——测试总结
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9388651.html
Copyright © 2011-2022 走看看