码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3507 Print Article —— 斜率优化DP

时间:2018-11-07 15:29:24      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:name   clu   using   ||   href   type   http   i++   article   

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507

设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m

即 f[j] + s[j]*s[j] = 2*s[i]*s[j] + f[i] - s[i]*s[i] - m

于是维护下凸包即可;

写成 double 的 slp 总是不对,把分母乘到对面就对了...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define db double
using namespace std;
typedef long long ll;
int const xn=5e5+5;
int n,m,q[xn];
ll f[xn],s[xn];
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();}
  while(ch>=0&&ch<=9)ret=(ret<<3)+(ret<<1)+ch-0,ch=getchar();
  return f?ret:-ret;
}
ll y(int i){return (ll)s[i]*s[i]+f[i];}
ll up(int i,int j){return y(i)-y(j);}
ll dn(int i,int j){return s[i]-s[j];}
db slp(int a,int b){return 1.0*(y(a)-y(b))/(s[a]-s[b]);}
int main()
{
  while(~scanf("%d%d",&n,&m))
    {
      memset(f,0,sizeof f);
      for(int i=1;i<=n;i++)scanf("%lld",&s[i]),s[i]+=s[i-1];
      int h=0,t=0;
      for(int i=1;i<=n;i++)
    {
      //while(h<t&&slp(q[h+1],q[h])<=2*s[i])h++;//<=  
      while(h<t&&up(q[h+1],q[h])<=2*s[i]*dn(q[h+1],q[h]))h++;//顺序
      f[i]=f[q[h]]+(ll)(s[i]-s[q[h]])*(s[i]-s[q[h]])+m;
      //while(h<t&&slp(q[t],q[t-1])>=slp(i,q[t-1]))t--;//>=
      while(h<t&&up(q[t],q[t-1])*dn(i,q[t-1])>=up(i,q[t-1])*dn(q[t],q[t-1]))t--;
      q[++t]=i;
    }
      printf("%lld\n",f[n]);
    }
  return 0;
}

 

hdu 3507 Print Article —— 斜率优化DP

标签:name   clu   using   ||   href   type   http   i++   article   

原文地址:https://www.cnblogs.com/Zinn/p/9922497.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!