DP 小结
前言
可能会分享一些本人觉得有意义有价值的题目,如果您可以爆切,也别喷我这个蒟蒻。
总结
DP 其实难在设状态和进行转移,也有很多优化,其中最本质的两种优化是数据结构优化和决策单调性优化。
题目
接下来,开始愉快 DP 之旅吧。
[POI2011] Lightning Conductor
题目大意
给定一个序列 \(a\),对于每个 \(i \in [1, n]\),求出最小的非负整数 \(p\),是的对于所有的 \(j \in [1, n]\) 都满足 \(a_j \le a_i + p - \sqrt {|i - j|}\)。
\(1 \le n \le 5 \times 10^5, 0 \le a_i \le 10^9\)。
思路
首先我们可以明显列出一个状态 \(f_i\) 表示答案,状态转移方程显然为:
显然发现这是前缀的情况,后缀的情况反一下就可以了。我们可以看出 \(\sqrt{i - j}\) 这个东西随着 \(j\) 的降低率在不断增大,不难想出其具有决策单调性,所以我们可以采用分治来解决这个问题(因为每次可以把可能决策点区间减小),复杂度很经典是 \(O(n \log_2 n)\)
「雅礼集训 2017 Day5」珠宝
题目大意
有 \(n\) 种物品,每种物品有钱数 \(c_i\) 和价值 \(v_i\),你需要对于所有 \(i \in [1, k]\),求出用 \(i\) 的总钱数能买到的最大价值是多少。
\(1 \le n \le 10^6, 1 \le k \le 5 \times 10^4, 1 \le c_i \le 300, 0 \le v_i \le 10^9\)。
思路
本题最大的亮点就在于 \(1 \le c_i \le 300\)。发现有很多物品的 \(c_i\) 是本质相同的,我们有发现一个经典结论:如果相同的 \(c_i\) 取得话,那么一定是选最大的一段,所以我们把相同的 \(c_i\) 排个序,然后搞出前缀和。发现转移就是下面这个柿子(\(f_i\) 表示恰好放了多少重量的最大价值):
其中 \(sum\) 就是前缀和。根据多重背包的经验之谈,我们可以优化到下面这个转移:
你考虑 \(sum(p, i)\) 会随着 \(p\) 的增大,他的增长率是不升的,类似于一个凸包,然后我们可以推出,对于 \(j > k\),他们的决策点 \(pos_j \ge pos_k\) 的,这个可以盲猜一波。
然后我们通过 cdq 分治去处理这种决策单调性的 DP 问题。
「PA 2019」Muzyka pop
题目大意
给你 \(n\) 个整数 \(a\),和一个整数 \(m\),请找到一个序列 \(b\) 满足 $ 0 \le b_1 \le b_2 \le ... \le b_n \le m$ 并且使得 \(\sum\limits_{i = 1}^{n} \text{popcount}(b_i) \times a_i\) 最大。
\(1 \le n \le 200, 1 \le m \le 10^{18}\)。
思路
显然如果当 \(m = 2^w - 1\),这个东西显然是可以通过区间 DP 解决的,显然可以将大区间划分为两个小区间,一半填 \(0\),一半填 \(1\),但是我们考虑它并不是这样的,所以我们对着 \(m\) 卡位,然后更新值就行。具体实现可以看代码。
BBQ Hard
题目大意
给出 \(n\) 个数对,要你求:
\(1 \le n \le 2 \times 10^5, 1 \le a_i, b_i \le 2000\)。
思路
首先我们考虑将 \(j = i + 1\) 变成 \(j = i\),这样答案就只需要除以 \(2\) 了。又因为重复了,所以答案要先加上减去所有的 \(\tbinom{2a_i + 2b_i}{2a_i}\)
我们考虑这个东西的组合意义,相当于从 \((0, 0)\) 走到 \((a_i + a_j, b_i + b_j)\) 的方案数,发现不好搞,平移一下,变成从 \((-a_i, -b_i)\) 走到 \((a_j, b_j)\) 的方案数,这个东西明显可以 DP 来搞,然后再按照如上方式处理就好了。具体的,给所有 \(f_{-a_i, -b_i}\) 加上一,然后跑 DP 后,把每个 \(i\) 的 \(f_{a_i, b_i}\) 统计一下就好了。

浙公网安备 33010602011771号