求集合中选一个数与当前值进行位运算的max
求集合中选一个数与当前值进行位运算的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的更多相关文章
- HDU 5735 Born Slippy(拆值DP+位运算)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5735 [题目大意] 给出一棵树,树上每个节点都有一个权值w,w不超过216,树的根为1,从一个点往 ...
- 趣题: 按二进制中1的个数枚举1~2^n (位运算技巧)
; ; k <= n; k++){ << k)-,u = << n; s < u;){ ;i < n;i++) printf(-i)&); print ...
- Hash值和位运算
一.Hash 1.md5是hash算法,不可逆,还原的是暴力穷举的方式解析的:加盐之后穷举也不能还原: 2.压缩映射会有重复,即哈希冲突: 二.ConcurrentHashMap 1.putIfAbs ...
- hdu 1856 求集合里元素的个数 输出最大的个数是多少
求集合里元素的个数 输出最大的个数是多少 Sample Input41 23 45 61 641 23 45 67 8 Sample Output42 # include <iostream&g ...
- poj 1611 求0号结点所在集合的元素个数
求0号结点所在集合的元素个数 Sample Input 100 42 1 25 10 13 11 12 142 0 12 99 2200 21 55 1 2 3 4 51 00 0Sample Out ...
- [note]一类位运算求最值问题
[note]一类位运算求最值问题 给定一些数,让你从中选出两个数a,b,每次询问下列中的一个 1.a and b的最大值 2.a xor b的最大值 3.a or b的最大值 神仙们都是FWT,小蒟蒻 ...
- DFS算法-求集合的所有子集
目录 1. 题目来源 2. 普通方法 1. 思路 2. 代码 3. 运行结果 3. DFS算法 1. 概念 2. 解题思路 3. 代码 4. 运行结果 4. 对比 1. 题目来源 牛客网,集合的所有子 ...
- [LeetCode] Count Complete Tree Nodes 求完全二叉树的节点个数
Given a complete binary tree, count the number of nodes. Definition of a complete binary tree from W ...
- BC68(HD5606) 并查集+求集合元素
tree Accepts: 143 Submissions: 807 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65 ...
随机推荐
- spring security运行流程图(转)
原文:http://blog.csdn.net/u011511684/article/details/31394493 示例下载地址:http://download.csdn.net/detail/u ...
- java 8中抽象类与接口的异同
1.java 8中抽象类与接口的异同 相同点: 1)都是抽象类型: 2)都可以有实现方法(以前接口不行): 3)都可以不需要实现类或者继承者去实现所有方法,(以前不行,现在接口中默认方法不需要实现者实 ...
- Zk搭建(Zookeeper)
第一步: 上传----解压 tar -zxvf zookeeper-3.4.5.tar.gz---- 配置zk的环境变量 ----------配置源码 vim ...
- js总结:对于字符串的切割截取和合并
1.函数:split() 功能:使用一个指定的分隔符把一个字符串分割存储到数组 例子: str=”jpg|bmp|gif|ico|png”; arr=str.split(”|”); //arr是一个包 ...
- Java8 Stream实例--统计出所有含‘张’字的人员的平均年龄
package com.zhangxueliang.demo; import java.util.ArrayList; import java.util.List; import java.util. ...
- Linux 的相关操作
切换权限 在linux环境下,用户之前的切换使用 “su - name,若要切换到root下面,则使用sudo su 命令即可. 在linux下安装软件,经常就是装完后不知道装到哪里去了 (201 ...
- 关于解决Missing Number之类的算法问题
停止刷题已经三周了,有些想念.最近总算完成了公司代码的重构,于是要继续开始学习算法. 先来看leetcode上面第268题: Given an array containing n distinct ...
- 莫烦sklearn学习自修第七天【交叉验证】
1. 什么是交叉验证 所谓交叉验证指的是将样本分为两组,一组为训练样本,一组为测试样本:对于哪些数据分为训练样本,哪些数据分为测试样本,进行多次拆分,每次将整个样本进行不同的拆分,对这些不同的拆分每个 ...
- Appium之开发环境搭建
1.下载Appium 去官方网站下载http://appium.io/# : 本次以appium-desktop-setup-1.8.0.exe 文件为例,使用桌面版就不再需要下载server版本: ...
- python numpy笔记(重要)
1.np.array 的shape (2,)与(2,1)含义 ndarray.shape:数组的维度.为一个表示数组在每个维度上大小的整数元组.例如二维数组中,表示数组的“行数”和“列数”. ndar ...