hdu-3507-Print Article

/*
第一次弄斜率dp,发现它真的很强大,和用线型单调队列来优化dp思路差不多;这里也是维持一个单调的斜率队列,保证每个点最多只进队一次;时间复杂对由然来的o(n×n)降到了o(n);主要是要弄出当G(i,j)<G(j,k)时,可以去掉j点用这个特点来优化,以及当G(q[head+1],q[head])<=sum[i]时,q[head+1]比q[head]优,那么q[head]就可以去掉了,且永远没用了,因为sum[i]是一直递增的,这也是一个特点,只要符合这两个特点的话就可以试着用斜率来优化状态方程了;斜率优化真是好方法;

*/


 

#include<stdio.h>
#include<string.h>
__int64 dp[510000],sum[510000];
__int64 G(int i,int j){return dp[i]+sum[i]*sum[i]-dp[j]-sum[j]*sum[j];}
__int64 g(int i,int j){return 2*sum[i]-2*sum[j];}
int q[510000];
int main()
{
 int n,m,i,head,tail;
 while(scanf("%d%d",&n,&m)!=EOF)
 {
  for(i=1,sum[0]=0;i<=n;i++)
  {
   scanf("%I64d",&sum[i]);
   sum[i]+=sum[i-1];
  }
  head=0;
  tail=1;
  memset(q,0,sizeof(q));
  memset(dp,0,sizeof(dp));
  for(i=1;i<=n;i++)
  {
   while(head+1<tail&&G(q[head+1],q[head])<=sum[i]*g(q[head+1],q[head]))head++;
   dp[i]=dp[q[head]]+m+(sum[i]-sum[q[head]])*(sum[i]-sum[q[head]]);
   while(head+1<tail&&G(i,q[tail-1])*g(q[tail-1],q[tail-2])<=G(q[tail-1],q[tail-2])*g(i,q[tail-1]))tail--;
   q[tail++]=i;
  }
  printf("%I64d\n",dp[n]);
 }
 return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值