[BZOJ3437]小P的牧场(斜率优化dp)

题目描述

传送门

题解

这种题就是用来水的。。。
fi=max{fj+sj+1sidi(cj+1ci)+ai}
si表示总费用和,di表示距离(相当于题目中有多少个点),ci表示放养数量,ai表示费用,都是后缀和。
喔然后斜率优化。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
const int max_n=1e6+5;

int n,head,tail,q[max_n];
LL a[max_n],b[max_n],c[max_n],d[max_n],s[max_n];
LL f[max_n];

inline LL K(int j){return -c[j+1];}
inline LL B(int j){return f[j]+s[j+1];}
inline LL Y(int i,int j){return K(j)*d[i]+B(j);}
inline bool cmp(int x1,int x2,int x3){
    LL w1=(K(x1)-K(x3))*(B(x2)-B(x1));
    LL w2=(K(x1)-K(x2))*(B(x3)-B(x1));
    return w1<=w2;
}

int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;++i) scanf("%lld",&a[i]);
    for (int i=1;i<=n;++i) scanf("%lld",&b[i]);
    for (int i=n;i>=1;--i) c[i]=c[i+1]+b[i];
    for (int i=n-1;i>=1;--i) d[i]=d[i+1]+1;
    for (int i=n;i>=1;--i) s[i]=s[i+1]+b[i]*d[i];

    head=tail=0;
    for (int i=1;i<=n;++i){
        while (head<tail&&Y(i,q[head])>=Y(i,q[head+1])) head++;
        f[i]=Y(i,q[head])-s[i]+c[i]*d[i]+a[i];
        while (head<tail&&cmp(i,q[tail-1],q[tail])) tail--;
        q[++tail]=i;
    }
    printf("%lld",f[n]);
}

你可能感兴趣的:(dp,bzoj)