P2120 [ZJOI2007]仓库建设(dp+斜率优化)

思路

首先暴力DP显然,可以得20分

加上一个前缀和优化,可以得到40分

然后上斜率优化

(sum_i)(sum_{1}^iP_i)(sump_i)(sum_{1}^{i}P_i imes Pos_i)

则决策j优于决策i的条件可以表示为

[dp_j+C_t+pos_t imes(sum_t-sum_{j}) - (sump_t - sump_{j})<dp_i+C_t+pos_t imes(sum_t-sum_{i}) - (sump_t - sump_{i}) ]

化简即可

这里贴上我认为写的不错的一篇题解其实是懒得写式子了

dummy的题解

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
int dp[1000010],n,c[1000010],p[1000010],pos[1000010],sum[1000010],summ[1000010];
int queue[1000010],h,t;
int T(int x){
    return dp[x]+summ[x];
}
int S(int x){
    return sum[x];
}
signed main(){
    // freopen("6.in","r",stdin);
    memset(dp,0x3f,sizeof(dp));
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld %lld %lld",&pos[i],&p[i],&c[i]);
        sum[i]=sum[i-1]+p[i];
        summ[i]=summ[i-1]+p[i]*pos[i];
    }
    dp[0]=0;
    // dp[1]=c[1];
    for(int i=1;i<=n;i++){
        while(h<t&&1.0*(T(queue[h+1])-T(queue[h]))/((S(queue[h+1])-S(queue[h])))<pos[i])
            h++;
        dp[i]=dp[queue[h]]+pos[i]*(sum[i]-sum[queue[h]])-(summ[i]-summ[queue[h]])+c[i];
        while(h<t&&1.0*(T(i)-T(queue[t]))/((S(i)-S(queue[t])))<1.0*(T(queue[t-1])-T(queue[t]))/((S(queue[t-1])-S(queue[t]))))
            t--;
        queue[++t]=i;
    }
    printf("%lld
",dp[n]);
    return 0;
}
原文地址:https://www.cnblogs.com/dreagonm/p/10129500.html