设
si 表示
a 的前缀和。最基本的想法是
dp,令
fi(j) 表示考虑到坐标为
i 的位置,使用了
j 个加固材料的最小花费,枚举当前位置有几个加固材料进行转移:
fi(j)=0≤k≤j−biminfi−1(k)+∣j−si∣。答案为
fn(sn)。
时间复杂度是
O(nsn2) 的,显然过不去,考虑使用
slope trick 优化。把转移方程的绝对值拆开,可得
fi(j)=0≤k≤j−biminfi−1(k)+max(0,j−si)+max(0,si−j)。
所以维护拐点(斜率变化点)只需要先平移,然后取前缀最小值,最后加入两个基本分段线性凸函数即可。注意两个细节:
- 答案是 sn 位置的函数值,并非整个函数的最小值;
- 任何位置的加固材料都需 ≥ 需要的材料数量,所以需要提前在堆里面放 n 个 0。
时间复杂度
O(nlogn),
提交记录。
附注:
官方题解好像做法不是
slope trick 优化
dp?但我没太看懂。