【BZOJ3437】小P的牧场,斜率优化DP

来源:互联网 发布:淘宝客 返利网 编辑:程序博客网 时间:2024/05/16 15:49

传送门
写在前面:感觉线性基太蛋疼了
思路:
原始方程
f[i]=min(f[j]+ik=j+1b[k](ik)+a[i])j[0,i)
用前缀和优化
f[i]=min(f[j]+i(sum1[i]sum1[j])(sum2[i]sum[j])+a[i])
其中sum1[x]=xi=1b[i],sum2[x]=xi=1b[i]i
复杂度O(n2)
设x>y且x转移i比y转移i优,则有
(f[x]+sum2[x]f[y]sum2[y])sum1[x]sum1[y]<i
注意:数据范围不全,a,b也属于long long范围
代码:

#include<bits/stdc++.h>#define LL long long#define M 1000003using namespace std;LL in(){    LL t=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9') t=(t<<3)+(t<<1)+ch-48,ch=getchar();    return t;}int n,head=1,tail=1,q[M];LL a[M],b[M],f[M],sum1[M],sum2[M];double Get(int x,int y){    return (double)(f[x]+sum2[x]-f[y]-sum2[y])/(double)(sum1[x]-sum1[y]);}main(){    n=in();    for (int i=1;i<=n;i++) a[i]=in();    for (int i=1;i<=n;i++)        b[i]=in(),        sum1[i]=sum1[i-1]+b[i],        sum2[i]=sum2[i-1]+b[i]*i;    for (int i=1;i<=n;i++)    {        while (head<tail&&Get(q[head+1],q[head])<i) head++;        f[i]=f[q[head]]+(sum1[i]-sum1[q[head]])*i-(sum2[i]-sum2[q[head]])+a[i];        while (head<tail&&Get(i,q[tail])<Get(q[tail],q[tail-1])) tail--;        q[++tail]=i;    }    printf("%lld",f[n]);}
0 0
原创粉丝点击