动态规划例题

不能很清晰地分类……就全丢到这里了……

Codeforces 2107 F1

TP Link
Submission

我们考虑 apa_p,我们可以这样做:

  • 花费 ipi-papa_p 换到自己前面
  • 花费 apa_p 超车
  • 再花费 11apa_p 换到自己面前
  • 再花费 apa_p 超车……

于是我们可以利用 apa_p 超车一个区间 ([l,r],lpr[l,r],l\le p\le r) 的车手,花费为(假设当前正在 rr 的身后)

(rl+1)ap超车费用+rl把 ap 从身后换到身前+rp把 ap 从原来的位置换到自己身前\begin{array}{rlll}(r-l+1)\cdot a_p &超车费用\\+r-l &把\ a_p\ 从身后换到身前\\+r-p &把\ a_p\ 从原来的位置换到自己身前\end{array}

当我们从 rrll 扫描的时候,此时我们枚举的 pp 递减,因此 rpr-p 递增,要使这个式子最小,apa_p 必须为 [l,r][l,r] 内最小值(且最靠右),才有可能最小化这个式子。

解决完这个区间之后,我们发现,整个 [1,n][1,n] 可以切分成多个这样的子结构(每个小区间里选出自己的 apa_p。差不多就类似于走进另一个区间发现在另一个区间用另一个数当 apa_p 更划算。

现在我们来定义状态。设 dp[i]dp[i] 表示从第 nn 个人后面走到第 ii 个人后面、第 i+1i+1 个人前面时所需要的最小费用。那么 dp[0]dp[0] 就是我们需要的答案,初始化 dp[n]=0dp[n]=0.

随后,我们从后向前枚举 ii(现在在第 ii 个人后面),并且枚举 jj,表明我们要从 ii 走到 jj 位置,即 dp[i]dp[j]dp[i]\to dp[j].

根据上文的分析,我们需要知道 a[ji]a[j\dots i] 的最小值 a[p]a[p](有多个的话取最右的,这个可以在枚举 jj 时一起维护)

dp[j1]mindp[i]+a[p]×(ij+1)超车费用+ip第一次换到身前+ij换到身前(jpi)dp[j-1]\underset{\min}{\gets} dp[i]+\underbrace{a[p]\times(i-j+1)}_{超车费用}+\underbrace{i-p}_{第一次换到身前}+\underbrace{i-j}_{换到身前} (j\le p\le i)

因为 a[p]a[p] 考虑了 a[j]a[j],所以 jj 位置也会被超车,因此更新的是 dp[j1]dp[j-1]