这个题目要是顺着dp的话很难做,但是倒着推就很容易退出比较简单的关系式了。

dp[i]=min(dp[u]+(sum[u-1]-sum[i-1]+s)*f[i]);dp[i]代表从i到结尾需要花费的代价,sum[i]表示1到i的时间和,f[i]代表i到n的代价和。

然后对于i状态来说,j由于k等价于 (dp[j]-dp[k])/(sum[k-1]-sum[j-1])<f[i]

然后f[i]随着i递减而递增,所以就可以利用斜率优化的办法来搞了。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e4+9;
long long sum[maxn],f[maxn];
long long dp[maxn];
int que[maxn]; bool chk1(int k,int j,int i)
{
return (dp[j]-dp[k])<f[i]*(sum[k-1]-sum[j-1]);
} bool chk2(int k,int j,int i)
{
return ((dp[j]-dp[k])*(sum[j-1]-sum[i-1]))>((dp[i]-dp[j])*(sum[k-1]-sum[j-1]));
} int main()
{
int n,s;
while(scanf("%d %d",&n,&s)!=EOF)
{
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%lld %lld",&sum[i],&f[i]);
sum[i]+=sum[i-1];
}
for(int i=n-1;i>=1;i--) f[i]+=f[i+1]; int front=1,end=0;
que[++end]=n+1;
dp[n+1]=0;
for(int i=n;i>=1;i--)
{
while(front<end&&chk1(que[front],que[front+1],i))
front++;
int u=que[front];
dp[i]=dp[u]+(sum[u-1]-sum[i-1]+s)*f[i];
while(front<end&&chk2(que[end-1],que[end],i))
end--;
que[++end]=i;
}
printf("%lld\n",dp[1]);
}
return 0;
}

最新文章

  1. android下拉框
  2. Android 6.0 新功能及主要 API 变更
  3. shell 和awk性能对比
  4. 【转】android shape的使用
  5. 这些git技能够你用一年了
  6. mvc4 http错误403.14 forbidden
  7. LLVM在静态分析上的增强 @ WWDC 2013
  8. 【树状数组】CSU 1811 Tree Intersection (2016湖南省第十二届大学生计算机程序设计竞赛)
  9. C51函数的递归调用
  10. AzureDev 社区活动获奖者公布
  11. Log4net日志记录、详细配置(自己使用)
  12. C#读取固定文本格式的txt文件
  13. babel简介
  14. Practical Lessons from Predicting Clicks on Ads at Facebook
  15. web API简介(四):客户端储存之IndexedDB API
  16. Resolve Missing artifact Issue in maven
  17. AsnycLocal与ThreadLocal
  18. 使用devstack/pike部署多节点实验
  19. Silverlight实用窍门系列:57.Silverlight中的Binding使用(二)-数据验证
  20. scrapy保存csv文件有空行的解决方案

热门文章

  1. HDU 5800 To My Girlfriend 背包
  2. WebServices中Xml的序列化
  3. 【BZOJ】【1040】【ZJOI2008】骑士
  4. 图片放大镜插件 Cloud Zoom v3.1
  5. Hadoop的RPC框架介绍
  6. CSS 类名的单词连字符:下划线还是连接符?
  7. Unity3d之音效播放和调用手机震动
  8. Manacher算法 O(n) 求最长回文子串
  9. Xcode显示行号
  10. Java:内部类