题目大意:n个单词分成连续的若干段,每一段的费用为单词长度和的平方加m,求最下总费用。
原题来自:HDU 3507
给出 $N$ 个单词,每个单词有个非负权值 $C_i$ ,现要将它们分成连续的若干段,每段的代价为此段单词的权值和的平方,还要加一个常数 $M$,即 $(\sum C_i)^2+M$。现在想求出一种最优方案,使得总费用之和最小。
【输入】
包含多组测试数据,对于每组测试数据:
第一行包含两个整数 $N$ 和 $M$。
第二行为 $N$ 个整数。
【输出】
输出仅一个整数,表示最小的价值。
【输入样例】
5 5 5 9 5 7 5
【输出样例】
230
【提示】
数据范围与提示:\n对于全部数据,$0\le N\le 5 × 10^5,0\le M\le 1000$。
解题思路
状态转移方程:$f[i] = f[j] + (s[i]-s[j])^2 + v$
拆开移项可得:$f[i] + 2*s[i] * s[j] = f[j]+s[j]^2 + s[i]^2+v$
拆法:包含j的是变量,仅包含j的多项式放在一边,包含i和j的多项式放在另一边,即可得到一个斜率式子。
如看成y=kx+b,那么上式的y是$f[j]+s[j]^2$,x是s[j],斜率是2*s[i],b是个常数可以暂时不管。
由此,可以define出代码的3~6行。
1、在转移的时候,i的前驱有多个,对于两个前驱哪个好?两点形成的斜率小于k则后面的好!
在斜率k=2*s[i]确定的情况下,由于我们要求的是最小值,需要第一个碰到的点是“最低”的点,直线往上平移,斜率小会先碰到右边点,斜率大会先碰到左边点。
2、考虑维护斜率递增或者递减,这里维护递增,为什么?
如果斜率出现递减,那么中间那个点永远不会用于转移,因为ab斜率大则a好,如果b比a好,ab斜率小,bc斜率更小,那么c比b好。
因为斜率k随着i递增而递增,所以选择的时候,从头开始,遇到斜率小的删除队头;入队前,如果发现斜率递减,删除队尾。最优决策在开头。
原来是这样用的 😉