主要内容
形如这样的 ( 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);