【小结】bitset

bitset 是一种基于压位的数据结构。它把 bool 数组中每 \(64\) 位压为一个 ull 类型的数。

首先,它能省空间。ull 是 8 字节,而普通的 bool 数组是每位一个字节。64 位就是 64 字节。每 64 字节变成了 8 字节。所以空间 /8。

然后,它能省时间。对于 ull 类型,进行位运算是 \(\mathcal O(1)\) 的。所以记 \(w=64\),对 bitset 进行 &^>><< 以及对 2 个 bitset &^<<>> 都是 \(\mathcal O(n/w)\) 的。这可以用来优化 DP。

bitset 可以当做 bool 数组用。

一些二进制函数:

__builtin_popcount(x) 数 \(x\) 的二进制中 \(1\) 的个数。

__builtin_parity(x) 判断 \(x\) 二进制中 \(1\) 的奇偶性。

__builtin_ctz(x) 判断 \(x\) 二进制末尾有几个 \(0\)

__builtin_clz(x) 判断 \(x\) 二进制开头有几个 \(0\)

log2(x)=31-__builtin_clz(x)。

优势在于:这些 __builtin 函数都是 \(\mathcal O(1)\) 的。

bitset 的函数:

.any() 判断有没有 \(1\)。有就返回 \(1\)

.none() 判断有没有 \(1\)。有就返回 \(0\)

.count() 数有多少 \(1\)

这些都是 \(\mathcal O(n/w)\) 的。

还有一个东西:

for (i=B._Find_first();i!=B.size();i=B._Find_next(i)) cout<<i<<" ";

可以输出所有 \(1\) 的位置。其中 size、_Find_first 和 _Find_next 都是 \(\mathcal O(1)\) 的。整个过程的时间复杂度是 \(\mathcal O(n/w+1的个数)\) 的。

另一些 bitset 函数:

.set(x) 把 \(x\) 这一位变成 \(1\)

.set() 把所有位变成 \(1\)

.reset(x) 把 \(x\) 这一位变成 \(0\)

.reset() 把所有位变成 \(0\)

.flip(x) 把 \(x\) 反转。

.flip() 把整个数组反转。

一种非常猎奇的东西:

(unsigned long long*)&a

表示把 \(a\) \(0\sim 63\) 做成一个 ull,\(64\sim 127\) 做成一个 ull \(\dots\)

然后从左往右是 \(0\sim 63\) 位。相当于解压。

posted @ 2026-08-21 16:43  GUO120822  阅读(3)  评论(0)    收藏  举报