单调队列与斜率优化杂题

hdu3530 Subsequence

给定一个序列,求满足 (Aleqmax-minleq B) 的最长的子序列

(nleq10^6)

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

时间复杂度 (O(n))

代码


poj1180 [IOI2002]Batch Scheduling

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

(nleq10^4, Sleq50, 1leq T_i, F_ileq100)

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

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

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

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

可以斜率优化

(T_i=displaystylesum_{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) 天之后能赚到多少钱。

(1leq Wleq n, mleq2000, 1leq AP_i, BP_i, AS_i, BS_ileq1000)

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

[f_{i, j}=max(f_{i-1, j}, displaystylemax_{j-AS_ileq kleq j}{f_{i-W-1, k}+(k-j) imes AP_i}, max_{jleq kleq j+BS_i}{f_{i-W-1, k}+(k-j) imes BP_i}) ]

考虑其中第二个式子,将括号拆开,把 (j imes AP_i) 提出来得到 (displaystylemax_{j-AS_Ileq kleq j}{f_{i-W-1, k}+k imes AP_i}-j imes AP_i)

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

注意初值设置

时间复杂度 (O(nm))

代码

原文地址:https://www.cnblogs.com/Juanzhang/p/10979344.html