寒假培训1.20 位运算

这里写图片描述

补码: 负数 ~x+1 正数一样

<< >> & ! ~ 运算符…

这里写图片描述
取某位: (x>>pos)&1
这里写图片描述
将某些位置为1
x|(1<< i )
将某些位置为0
x&~(1<< i)
将某些位置取反
x^(1<< i)

求1的个数
1.查表 f[i]=f[i>>1]+(i&1)
分段 分成16位
这里写图片描述

如果内存很小怎么办……
这里写图片描述
(并没有听懂..)

求1的个数的奇偶性
这里写图片描述
把它拆成两个16位 xor一下 再拆成两个8位 xor一下 ……最后判一判是不是1 就好了

GCC内建函数
__builtin_parity

翻转位序
f(0) = 0
f(i) = (f(i >> 1) >> 1) | ((i & 1) << 15)
i处理到2^16

也可以这么搞
这里写图片描述
拆成1、2、4、8、16位 相邻的翻转就好了

求前缀OR后缀0的个数
这里写图片描述
这个看起来简单一些
求后缀零同理
(也可以查表)
f[0]=16;
f[i]=f[i>>1]-1; 把32位的数拆成两个16位的。搞定

第k个1的位置
二分+查表 (查一下有几个 同1的个数)

提取末尾连续的1
x & (x ^ (x + 1))

提取lowbit x&(-x)

bitset
count
find_first/find_next(GCC下 不是标准)

求集合中第k小元素
搞棵线段树

lower_bound()
1.搞棵线段树 前缀和 线段树上二分 O(n/w*logn)
这里写图片描述
就酱 把叶子换成64位整数 可以在整数内 用前面讲到的求第k大
2.搞棵线段树
这里写图片描述
这样子的 是一个“或”关系的线段树
中间存储就不用64位整数了
(好像线段树思路没有更好的办法了 换个角度)

3.搞个辅助的bitset (w叉线段树)
这里写图片描述
这里写图片描述
集合的与或非还是O(n)级别的改 就酱
O(logn/logw)
4.
这里写图片描述
Tree只有loglogn层 vebTree 但是修改的时候麻烦一点儿
理论上n大的时候有优势

枚举子集 (y-1)&x
这里写图片描述
(DFS一遍 也好啊……)

原文地址:https://www.cnblogs.com/SiriusRen/p/6532069.html