[CF878D] Magic Breeding 题解

你谷 link

CF link

又是一道 bitset 科技题,但是思维难度也还是很高的。

考虑先弱化一下题目,如果特征只有 \(0/1\) 该怎么做,考虑对于 \(0/1\) 来说,\(\min/\max\) 可以看成 \(\operatorname{bitand}/\operatorname{bitor}\) 操作,那么我们考虑如果将所有生物的一种特征单独做会怎么样,现在的问题就变成了给定一个数组,每次新生成一个元素表示为之前选取两个值的 \(\operatorname{bitand}/\operatorname{bitor}\),现在的情况是因为有 \(10^5\) 种特征,每一位单独做时间复杂度无法接受,但是发现因为初始数组只有 \(12\) 个生物,所以如果特征只有 \(0/1\) 的话最多只有 \(2^{12}=4096\) 种情况,时间复杂度并不是不能接受,而且可以用 bitset&| 操作加速,性质非常优秀。

考虑如何将 \(10^9\) 的值域转化成 \(0/1\),这可以说是一个经典套路,首先我们发现因为初始只有 \(12\) 个值,而 \(\min/\max\) 操作不会产生新的值,所以值最多只有 \(12\) 种,对于将大值域转化成 \(0/1\) 一个经典的手段在二分时经常用到,就是设一个阈值 \(\text{limit}\),如果一个值比 \(\text{limit}\) 小就是 \(0\),否则就是 \(1\),这里我们也可以照用,我们一共有 \(12\) 种阈值,难道每个都维护一遍吗?实际上不用这么麻烦。考虑前面我们发现一共就 \(4096\) 种情况,我们可以直接设任意一个值为 \(0/1\) 的情况,全部记录下来,即设 \(f_{i,sta}\) 表示 \(sta\) 对应的所有位置的值都为 \(1\) 的情况下第 \(i\) 个值是什么,然后发现因为 \(\min/\max\) 操作对应 \(\operatorname{bitand}/\operatorname{bitor}\),且在生成 \(i\) 时转移每个 \(sta\) 操作的方法是一样的,所以可以用 bitset 优化,然后查询操作直接从大到小枚举阈值更新 \(sta\) 直到答案为 \(f_{i,sta}=1\),初始化就是 \(f_{i,sta}=[i\subseteq sta]\)

代码并没有想象中那么难。

posted @ 2022-05-25 16:20  老莽莽穿一切  阅读(38)  评论(0编辑  收藏  举报