【学习笔记】bitset
例题cf878d
考虑只有 \(0,1\) 的情况:显然可以对 \(k\) 种生物,每种生物 \(i\) 都开一个大小为 \(n\) 的 bitset \(b_i\)。\(\max(x,y)\) 操作就是 \(b_x | b_y\),\(\min(x,y)\) 操作就是 \(b_x \& b_y\)。
拓展到一般情况:可以将 \(n\) 列的 \(k\) 个数字离散化到 \(1\sim k\) 的值域当中。假设 \(a_{i,j}=v\),可以将它变成 \(2^v - 1\),存到 bitset 中,这样原来的 \(nk\) 个数就以 \(0,1\) 的形式存到了 \(nk^2\) 大小的 bitset 中(每个数占用 \(k\) 大小的 bitset,有 \(nk\) 个数),这样就可以继续用 bitset 维护。时间复杂度 \(O(nkq/\omega+nk^2)\)。
考虑优化:发现维护了很多冗余的信息,因为最多只有 \(2^k\) 个本质不同的列,但是现在实际上维护了 \(nk\) 个列。考虑两个相同的列,不管怎么操作它们都还是相同的,因此不管如何操作,最后本质不同的列还是只有 \(2^k\)。
可以先预处理出 \(k\times 2^k\) 大小的 bitset,每次操作就把两个大小为 \(2^k\) 的 bitset 进行位运算,将新生成的一个 bitset 放到下面。设 \(id_{i,j}\) 表示第 \(i\) 大列,第 \(j\) 小列的类型(共 \(n\) 大列,每一大列有 \(k\) 小列),如果要查询 \(a_{i,j}\) 的值,可以先算出出 \(\sum_{s = 1}^k b_{i,id_{j,s}}\) 即可,即是第几大的数,然后在映射回离散化前的数值。时间复杂度 \(O(2 ^ kq/\omega + k/\omega)\)

浙公网安备 33010602011771号