单调队列与斜率优化杂题

hdu3530 Subsequence

给定一个序列,求满足 \(A\leq\max-\min\leq B\) 的最长的子序列

\(n\leq10^6\)

维护递增递减两个单调队列,若两队首之差大于 \(B\) ,挪动较小左端点,并更新答案左端点

时间复杂度 \(O(n)\)

代码


poj1180 [IOI2002]Batch Scheduling

\(n\) 个任务,每个任务有时间 \(T_i\) 与花费 \(F_i\) 。将这些任务分组,每组花费为 \((\)之前花费的时间\(+S+\displaystyle\sum T_i)\times (\sum F_i)\)

\(n\leq10^4,\ S\leq50,\ 1\leq T_i,\ F_i\leq100\)

首先可以设计出一个状态数为 \(n^2\) 时间复杂度为 \(O(n^3)\) 的dp,用斜率优化可以做到 \(O(n^2)\)

但这样空间会炸,考虑设计一个状态线性的dp

由于总时间 \(=k\times S+\displaystyle\sum_{i=1}^nT_i\) 。将一段区间分为一组会使得剩下的所有数的时间增加 \(S\) ,也就使得剩下的花费增加了 \(S\times \displaystyle\sum_{i=now+1}^nF_i\)

于是可以设计一个倒序dp,令 \(f_i\)\(i\)\(n\) 的任务分为若干组的最小花费,则 $$f_i=\displaystyle\min_{j>i}{f_j+(S+\displaystyle\sum_{k=i}{j-1}T_i)\times(\sum_{k=i}nF_i)}$$

可以斜率优化

\(T_i=\displaystyle\sum_{j=i}^nT_i,\ F_i=\sum_{j=i}^nF_i\)

\(f_j=F_iT_j+f_i-SF_i-T_iF_i\)

时间复杂度 \(O(n)\)

代码


bzoj1855 [SCOI2010]股票交易

一共有 \(n\) 天,每天买入价为 \(AP_i\) ,卖出价为 \(BP_i\) ,最多买入 \(AS_i\) 股,最多卖出 \(BS_i\) 股。两次交易至少间隔 \(W\) 天,任何时候最多持有 \(m\) 股。初始资金数目无限,求 \(n\) 天之后能赚到多少钱。

\(1\leq W\leq n,\ m\leq2000,\ 1\leq AP_i,\ BP_i,\ AS_i,\ BS_i\leq1000\)

\(f_{i,\ j}\) 为第 \(i\) 天,持有 \(j\) 股最多赚钱数目

\[f_{i,\ j}=\max(f_{i-1,\ j},\ \displaystyle\max_{j-AS_i\leq k\leq j}\{f_{i-W-1,\ k}+(k-j)\times AP_i\},\ \max_{j\leq k\leq j+BS_i}\{f_{i-W-1,\ k}+(k-j)\times BP_i\}) \]

考虑其中第二个式子,将括号拆开,把 \(j\times AP_i\) 提出来得到 \(\displaystyle\max_{j-AS_I\leq k\leq j}\{f_{i-W-1,\ k}+k\times AP_i\}-j\times AP_i\)

可以发现 \(\max\) 中只有与 \(k\) 相关的项,于是可以用单调队列优化

注意初值设置

时间复杂度 \(O(nm)\)

代码

posted @ 2019-06-05 14:21  cnJuanzhang  阅读(205)  评论(0编辑  收藏  举报