dp的优化总结

前缀和优化

解决问题 如果dp转移过程中需要反复的使用一个求和式时,可以将数列的前缀和先预处理出来。运算一般要满足可减性。

题目

单调队列优化

前置技能 单调队列(经典问题模型:P1886 滑动窗口题解

解决问题 优化形如 \(f_i = \min/\max\{ g_j\ |\ l_i \le j \le i - 1 \} + w_i\) ,且满足 \(l_i \le l_{i+1}\) 的转移。

解释 对于序列中的每个点,从其左侧一段决策区间内的最值进行转移,且决策区间随着序列下标的增大也不断右移,类似于窗口向右滑动。

解法 设 \(j<k\) ,容易发现如果 \(g_j\) 劣于 \(g_k\) 的话,那么当决策区间移动到 \(k\) 以后, \(j\) 永远不会成为最优决策点,再也不会被转移使用了。所以,我们要维护一个队列,满足下标递增决策性递减。我们需要当前的队首成为最优决策点,那么当队首第一次超出了区间范围(以后也就永远超出了)就把它出队。为了保证单调性,队尾新加入点之前,要先把队列中比它劣的点依次从队尾出队。

题目

决策单调性

解决问题 发现决策之间的递变规律。

  • 优化形如 \(f_i = \min/\max w_{i,j}\) 且对于每个 \(i\) 和它的最优决策点 \(j\) 都有单调性的转移方程。这类问题一般对题目的性质要求较高,因为 \(j\) 是独立的。只需要维护指针,按照单调性不断寻找最优答案即可。类似于尺取法。
  • 形如\(f_i = \min/\max\{ g_j\ |\ 1 \le j \le i - 1 \} + w_{i,j}\),且 \(f_i\) 的最优决策点为 \(p_i\) ,也就是 \(f_i\)\(g_{p_i} + w_{i,p_i}\) 处转移最优。若满足 \(p_i \le p_{i + 1}\) ,则该方程满足决策单调性。因为 \(j\) 不独立了,所以我们只能把有用的决策先存起来。使用如下策略。

策略1:二分栈

使用决策二分栈,一种单调栈来维护所有有用的决策。

二分栈 我们将 \(g_j + w_{i,j}\) 视为关于 \(j\) 的函数。因为决策单调,所以对于栈中的任意相邻两个决策点,我们都可以通过二分找到一个临界值 \(k\) ,使得序列中在 \(k\) 之前的时候,其中一个作为决策转移到 \(f_k\) 更优,而 \(k\) 以后另一个更优。

栈顶为当前的最优解。而如果栈中有不止一个元素,则可能存在一个 \(i\) ,使得到 \(i\) 之后栈里面的决策比栈顶优了,这时就需要弹栈。对于当前的 \(i\) ,如果当前栈顶下面与栈顶相邻的决策在 \(i\) 之前就比栈顶更优了,就要把栈顶弹掉。

策略2:分治

二分栈存在局限性,那就是必须能快速计算 \(w_{i,j}\) 。如果不能 \(O(1)\) 计算的话,在求临界值 \(k\) 的时候复杂度会严重退化。

由于转移过程是单调并且离线的,我们考虑分治。假设当前我们求解一段区间 \(f_{l,r}\) ,而所有 \(f_{l,r}\) 的最优决策点在 \([L,R]\) 之间。对于 \([l,r]\) 的中点 \(mid\) ,我们可以暴力扫一遍 \(L−mid\) ,找到它的最优决策点 \(k\)。因为决策单调,所以 \(f_{l,mid−1}\) 的决策落在 \([L,k]\) 上,而 \(f_{mid+1,r}\) 的决策落在 \([k,R]\) 上,变成了两个规模减半的小问题。时间复杂度为 \(O(n\log n)\)

斜率优化

形如 \(f_i = \min/\max\{ g_j\ |\ 1 \le j \le i - 1 \} + w_{i,j}\) 的转移方程式。

考虑决策 \(j_1\)\(j_2\) ,如果 \(j_1\)\(j_2\) 优,那么 \(g_{j_1} + w_{i, j_1} \le g_{j_2} + w_{i, j_2}\)
根据题目将 \(w\) 展开,如果可以化为 \(\frac{y_{j_1}-y_{j_2}}{x_{j_1}-x_{j_2}} \le k_i\) 的形式,那么我们把每个决策点看成 \((x_j,y_j)\) 分布在坐标系上,真正使用到的决策点形成的一个凸壳。

如果 \(x\) 单调,可以用单调栈维护凸壳,转移时使用当前直线的斜率(线性规划),在栈内二分最优解。
如果斜率 \(k\) 单调,那么用单调队列维护凸壳,队首为当前最优决策。转移之前如果队首不优就出队。

posted on 2019-08-10 16:09  solvit  阅读(154)  评论(0编辑  收藏  举报

导航