bzoj3156: 防御准备
题目链接
题解
到右侧的花费是不是很不顺眼啊,换成左侧的吧
然后dp方程写一写吧
然后就可以斜率优化一下了吧
然后没啦(大雾,偷一下懒辣
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
#define int long long
const int maxn = 1000007;
int n;
int a[maxn],q[maxn],sum[maxn],ans = 100000000007ll,dp[maxn];
double slop(int k,int j) {
return double (dp[k] - dp[j] - (sum[k] - sum[j]) + k * k - j * j + k - j) / double (k - j);
}
main() {
n = read();
for(int i = n;i >= 1;-- i) a[i] = read();
for(int i = 1;i <= n;++ i) sum[i] = sum[i - 1] + i;
dp[1] = a[1];q[1] = 1;int l = 1, r = 1;
for(int i = 2;i <= n;++ i) {
while(l < r && slop(q[l],q[l + 1]) < i) l ++;
int t = q[l];
dp[i] = dp[t] + sum[i - 1] - sum[t] - (i - t - 1) * t + a[i];
ans = std::min(ans,dp[i] + sum[n] - sum[i] - (n - i) * i);
while(l < r && slop(q[r - 1],q[r]) > slop(q[r],i)) r --;
q[++ r] = i;
}
printf("%lld\n",ans);
return 0;
}