思路
斜率优化。
f[i] 表示i点建检查点的花费。
f[i] = f[j] + i*(i-j-1)-(s[i-1]-s[j]) + a[i],从j转移,s为前缀和。
代码
1 #include<cstdio> 2 #include<iostream> 3 4 using namespace std; 5 6 typedef long long LL; 7 8 const int N = 1000100; 9 LL s[N],f[N],a[N]; 10 int q[N],L,R; 11 12 inline int read() { 13 int x = 0,f = 1;char ch = getchar(); 14 for (; !isdigit(ch); ch=getchar()) if(ch=='-') f=-1; 15 for (; isdigit(ch); ch=getchar()) x = x*10+ch-'0'; 16 return x * f; 17 } 18 double slope(int i,int j) { 19 return double(f[i]+s[i]-f[j]-s[j])/double(i-j); 20 } 21 int main() { 22 int n = read(); 23 for (int t,i=1; i<=n; ++i) { 24 t = read(); 25 a[i] = (LL)t; 26 s[i] = s[i-1] + (LL)i; 27 } 28 L = R = 1; 29 q[1] = 0; 30 for (int i=1; i<=n; ++i) { 31 while (L<R && slope(q[L],q[L+1]) < 1.0*i) L++; 32 int j = q[L]; 33 f[i] = f[j] + 1ll*i*(i-j-1) - (s[i-1]-s[j]) + a[i]; // i*(j-1)需要变成longlong 34 while (L<R && slope(q[R-1],q[R]) > slope(q[R],i)) R--; 35 q[++R] = i; 36 } 37 cout << f[n]; 38 return 0; 39 }