寒假培训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一遍 也好啊……)