bzoj3437: 小P的牧场

题目链接

bzoj3437: 小P的牧场

题解

dp转移有点玄学....好神的前缀和呀quq可能当时做时心态不太好 ?QAQ
令$$sum[i]=\sum_{k=1}{i}b[k],cost[i]=\sum_{k=1}{i}{b[k]*k}$$
得出dp方程

\[dp[i]=\min_{k=0}^{i-1}\{dp[k]+b[k]+(sum[i]-sum[k+1])*i-(cost[i]-cost[k+1])\} \]

然后就是斜率优化的套路了

代码

#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 a[maxn],b[maxn],q[maxn]; 
int n,dp[maxn]; 
int sum[maxn],cost[maxn];
//dp[i] = min{dp[j]+(sum[i]-sum[j])*i-(cost[i]-cost[j])} +a[i]
double slop(int k,int j) {
    return double (dp[j] - dp[k] + cost[j] - cost[k]) / double (sum[j] - sum[k]);
}
 
main() {
    n = read(); 
    for(int i = 1;i <= n;++ i) a[i] = read(); 
    for(int i = 1;i <= n;++ i) b[i] = read(); 
    for(int i = 1;i <= n;++ i) sum[i] = sum[i - 1] + b[i], cost[i] = cost[i - 1] + b[i] * i;
    int l = 0,r = 0;
    for(int i = 1;i <= n;++ i) {
        while(l < r && slop(q[l],q[l + 1]) < i) l ++;
        int t = q[l];
        dp[i] = dp[t] + (sum[i] - sum[t]) * i - (cost[i] - cost[t]) + a[i];
        while(l < r && slop(i,q[r]) < slop(q[r],q[r - 1])) r --;
        q[++ r] = i;
    }
    printf("%lld\n",dp[n]);
    return 0;
}

posted @ 2018-05-02 20:02  zzzzx  阅读(99)  评论(0编辑  收藏  举报