bitset 学习笔记
bitset的若干用法
未经题目和前文定义的字母默认为全空的bitset。
Problem 1
对于一个数组 \(a_{[1,n]}\),对于 \(1\le i,j\le n\),将 \(a_i+a_j\) 标记出来。\(n\le 10^5\)
对于 \(a_i\),先将所有的 \(h_{a_i},g_{a_i}\) 标记为 \(1\)。然后对于所有 \(a_i\),将 h|=(g<<a[i])。时间复杂度 \(O(\frac {n^2} {w})\)。
- 需要将原数组标记出
h|=g,没有额外时间开销
- 要求 \(i\neq j\)。
如果存在 \(i\neq j,a_i=a_j\),预先在 h 中标记出来。
b[a[i]]=1
h|=((g^b)<<a[i])
Problem 2
对于一个数组 \(a_{[1,n]}\),对于 \(1\le i,j\le n,a_i\ge a_j\),将 \(a_i-a_j\) 标记出来。\(n\le 10^5\)
对于 \(a_i\),先将所有的 \(h_{a_i},g_{a_i}\) 标记为 \(1\)。然后对于所有 \(a_i\),将 h|=(g>>a[i])。时间复杂度 \(O(\frac {n^2} {w})\)。
变种的处理方式类推。
Problem 3
埃氏筛素数:
时间复杂度没有变化。但是空间是 \(O(\frac nw )\),实测相比布尔数组的欧拉筛在 \(n=10^8\) 数据下快 \(6\%\),比布尔数组的埃氏筛快 \(37\%\)。
欧拉筛素数:
bitset 是负优化。因为访问太分散。
Problem 4
一个文本串 \(s\),若干个模板串 \(t\)。求出现次数 或者 是否匹配 或者 匹配位置。\(|s|\le 10^5,\sum|t|\le 2\times 10^5\),设字符集大小为 \(S\)。
这是 AC 自动机板子题。我们考虑 bitset 做法。我们开 \(S\) 个 bitset,维护每种字符的出现位置。
在查找一个字符串 t 时,将对应字符的bitset错误就可以得到最后的匹配数组。代码中的 ans 存储了是否匹配的布尔量。可以用各种函数(例如 .count() 求出需要的各种信息)
for(int i=0;i<len;i++)ans&=c[t[i]-'a']<<len-i-1;
时间复杂度 \(O(\frac{|s|\sum|t|}{w})\)
如果卡得很紧而且要知道具体哪些位置是 1,bitset 可以在 \(O(\frac n w)\) 的时间内求出第一个 1 和下一个 1。
比 AC 自动机的好处是
- 好写
- 好带修
Problem 5
优化 Floyd,当然只能优化连通性问题。
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
if(a[i][k]) a[i]|=a[k]
}
}
由于常数极小,甚至可以过 \(n\le 3000\) 的数据。
Problem 6
dp 配合 bitset
如果 dp 是 01-dp,就可以把 bool 数组改成 bitset,几乎没有坏处。而且可能能一定程度上减小常数。
如果 dp 涉及整行整列做二进制操作,就可以用 bitset 做。
Problem 7
莫队配合 bitset
以 P3674 举例
三个操作分别可以理解为:
- 是否同时出现了 \(y\) 和 \(y+x\)
- 是否同时出现了 \(N-b\) 和 \(N-a+x\)。
- Proof:\(a+b=x\leftrightarrow a-(N-b)=x-N\leftrightarrow(N-b)-a=N-x\leftrightarrow (N-b)-x=(N-a)\)
与减法一样维护,只不过这次要维护一个新的 bitset 是 \(N-x\) 存不存在
- Proof:\(a+b=x\leftrightarrow a-(N-b)=x-N\leftrightarrow(N-b)-a=N-x\leftrightarrow (N-b)-x=(N-a)\)
- 是否同时存在了 \(v\) 和 \(\frac x v\)。
最后一个本来就可以平方维护。
前两个已经被我们转化成了 bitset 问题,猜你想搜 Problem 1。
时间复杂度 \(n^2(\sqrt n+\frac n w)\)。

浙公网安备 33010602011771号