斜率优化DP

主要内容

形如这样的 ( ext{DP}) 转移方程:

[dp[i]=max_{L_ile jle R_i}{dp[j]+val(i,j)} ]

满足:

  • ({L_i})({R_i}) 递增( 前提条件 )。

  • (R_i≤i) ( 转移条件 )。

  • (val(i,j))(i)(j) 相关(若只与 (j) 有关可以用单调队列优化DP)。

我们考虑将其变形:(先假设方程为 (dp[i]=max_{L_ile jle R_i}{dp[j]+i imes j})

[dp[i]=max_{L_ile jle R_i}{dp[j]+i imes j} ]

直接拆掉 (max)

[dp[i]=dp[j]+i imes j ]

[dp[j]=-i imes j+dp[i] ]

[[y]=[k] imes [x]+[b] ]

即:

  • 将只与 (j) 有关的放在左边作为 ([y])

  • (i,j) 都有关的放在中间做一次项,其中 (i) 做系数而 (j) 做变量。

  • 将只与 (i) 有关的放在右边做常数。

之后按照斜率的单调性直接转移。

咕咕咕:cdq 以及线段树优化等。

例题:

P4072 [SDOI2016]征途

非常裸的斜率优化,但是要注意值域较大,应该先将式子化简,减小运算的大小,防止运算过程中爆 ( exttt{long}~ exttt{long})

P2120 [ZJOI2007]仓库建设

需要注意的是,这道题可能不用将 (n) 的元素全部分配玩(因为末尾可能有连续的 (0) 使不用在 (n) 处再分一段)。

因此我们需要再输出答案之前将答案与末尾所有连续非 (0) 的取 (min) ,保证取到最大值。

(min) 代码:

ans=dp[n];
for(int i=n;i>=1;i--)
	 if(!p[i+1]) ans=minll(ans,dp[i]);
	 else break;
printf("%lld
",ans);
原文地址:https://www.cnblogs.com/EricQian/p/15132345.html