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\) 存不存在
  • 是否同时存在了 \(v\)\(\frac x v\)

最后一个本来就可以平方维护。

前两个已经被我们转化成了 bitset 问题,猜你想搜 Problem 1。

时间复杂度 \(n^2(\sqrt n+\frac n w)\)

posted @ 2024-02-29 15:01  wtcqwq  阅读(18)  评论(0)    收藏  举报