您的位置:首页 > 其它

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

2016-04-29 15:22 357 查看
传送门

写在前面:感觉线性基太蛋疼了

思路:

原始方程

f[i]=min(f[j]+∑ik=j+1b[k]∗(i−k)+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 1000003
using 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
);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: