bzoj3156: 防御准备

题目链接

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; 
}
posted @ 2018-05-02 19:44  zzzzx  阅读(145)  评论(0编辑  收藏  举报