dp斜率优—2

来源:互联网 发布:linux最大连接数65536 编辑:程序博客网 时间:2024/06/05 15:44

hdu4258

题目大意:将n个升序数字序列,分成几组连续的序列 ,每一组的所得值,等于最右边的num2减去最左边 的num1,的平方+c即(numi-numj)^2+c

解题报告 人:GHQ(SpringWater)

分析可得:(dp[j2]-dp[j1]+num[j2+1]*num[j2+1]-num[j1+1]*num[j1+1])/(2(num[j2+1]-num[j1+1]))<=num[i]时,j2比j1更优,可知这是一个凹曲线斜率优化;

i<j<k时且k(i,j)>=k(j,k)时,那么j是可以去掉的。

1.当 k(j,k)<=num[i]时,j没 k优,可去 j

2.当 k(j,k)>=num[i]时,则k(i,j)>=num[i],i比j优秀,可去j!

总结 一下 能斜率优化的题目大概:先设 看k<j<i  (f[k]-f[j])/(d[k]-d[j])<=k[i]  k[i] 一定要递增
是可以化成
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<queue>#define maxn 1000005using namespace std;typedef long long LL;LL n,a[maxn];LL dp[maxn];int que[maxn];double judge_k(int x,int y){    return (double)(dp[x]+a[x+1]*a[x+1]-(dp[y]+a[y+1]*a[y+1]))/((double)(2.0*(a[x+1]-a[y+1])));}int main(){    int c;    while(scanf("%I64d %d",&n,&c)!=EOF)    {        if(n==0&&c==0)            break;        for(int i=1;i<=n;i++)            scanf("%I64d",&a[i]);        dp[0]=0;        que[0]=0;                int l=0,r=0;        for(int i=1;i<=n;i++)        {            while(l<r&&judge_k(que[l],que[l+1])<=a[i]) l++;            dp[i]=dp[que[l]]+c+(a[i]-a[que[l]+1])*(a[i]-a[que[l]+1]);            while(l<r&&judge_k(que[r],i)<=judge_k(que[r],que[r-1])) r--;            que[++r]=i;        }        printf("%I64d\n",dp[n]);    }    return 0;}


1 0
原创粉丝点击