题意
1~n放城堡/木偶,在第i位放城堡的 \(\ cost_i\) 给出,放木偶的 \(\ cost_i = (j-i)\)(j为i右边第一个城堡)
问最小花费
题解
普通\(\theta{(n^2)}\)Dp会挂 \(\ n\leq 100000\)
需要斜率优化,为了方便,我们从左往右Dp
f[i] 为在这个点放城堡的最小花费(因为第n个必须放城堡)
fi=minj<iai+fj+1+2+⋯+(i−j−1)(j为i左边第一个城堡) f_i=\min\limits_{j<i}{a_i+f_j+1+2+\dots+(i-j-1)} (j为i左边第一个城堡)fi=j<iminai+fj+1+2+⋯+(i−j−1)(j为i左边第一个城堡)
化简得fi=minj<iai+fj+(i−j)×(i−j−1)化简得 f_i=\min\limits_{j<i}{a_i+f_j+(i-j)\times(i-j-1)}化简得fi=j<iminai+fj+(i−j)×(i−j−1)
fi=minj<ifj+j(j−1)2+ij+ai+i(i−1)2f_i=\min\limits_{j<i}{f_j+\frac{j(j-1)}{2}+ij+a_i+\frac{i(i-1)}{2}}fi=j<iminfj+2j(j−1)+ij+ai+2i(i−1)
设xj=j,yj=fj+j(j−1)2设x_j=j, y_j=f_j+\frac{j(j-1)}{2}设xj=j,yj=fj+2j(j−1)
然后斜率优化
调试记录
\(\ y_j\)找错
#include <cstdio>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
#define maxn 1000005
#define int long long
using namespace std;
int f[maxn], q[maxn], a[maxn];
int l, r, n, sum[maxn];
int Y(int id){ return f[id] + sum[id]; }
double slope(int id1, int id2){ return 1.0 * (Y(id2) - Y(id1)) / (id2 - id1); }
signed main(){
scanf("%lld", &n); sum[0] = 0;
for (int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + i;
}
l = 0, r = 0;
for (int i = 1; i <= n; i++){
while (l < r && slope(q[l], q[l + 1]) <= i) l++;
int j = q[l];
f[i] = Y(j) - i * j + a[i] + sum[i - 1];
while (l < r && slope(q[r - 1], q[r]) >= slope(q[r], i)) r--;
q[++r] = i;
}
printf("%lld\n", f[n]);
return 0;
}