放一手原题


题解:

第一次写(抄)斜率优化,心里还是有点小激动的。讲一下怎么实现的!

首先我们可以考虑一个朴素的dp:DP[i]表示前i个数字的最少花费,显然我们有一个转移方程

DP[i]=min{DP[j]+M+(sum[i]-sum[j])^2}

但是N^2肯定会超时,我们考虑优化他

假设有k<j<i,如果令j对i的贡献比k好

显然我们有这样的式子

DP[j]+M+(sum[i]-sum[j])^2 < DP[k]+M+(sum[i]-sum[j])^2

把平方打开之后移项

可以得到

 ((DP[j]+sum[j]^2)- (DP[k]+sum[k]^2) )  / 2*(sum[j]-sum[k]) < sum[i]

可以把这个式子看成(yj - yk)/(xj - xk) 这样就得到了一个类似斜率的式子!

有了这些结论有什么用呢?

令G[i,j]表示刚刚的斜率式,依然有k<j<i

当j的决策比k优秀的时候,则满足G[i,j]>G[j,k]

我们可以用单调队列维护解集,利用斜率判断元素的入队和出队,这样可以使时间复杂度降低到O(n)了

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 500005
using namespace std;
int dp[N],q[N],sum[N],l,r,n,m;
int GetDp(int i,int j)
{
return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
}
int GetUp(int j,int k)
{
return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]);
}
int GetDown(int j,int k)
{
return *(sum[j]-sum[k]);
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
for (int i=,x;i<=n;i++)
scanf("%d",&x),sum[i]=sum[i-]+x;
l=r=;
q[r++]=;
for (int i=;i<=n;i++)
{
while (l+<r && GetUp(q[l+],q[l])<=sum[i]*GetDown(q[l+],q[l]))
l++;
dp[i]=GetDp(i,q[l]);
while (l+<r && GetUp(i,q[r-])*GetDown(q[r-],q[r-])<=GetUp(q[r-],q[r-])*GetDown(i,q[r-]))
r--;
q[r++]=i;
}
printf("%d\n",dp[n]);
}
return ;
}

最新文章

  1. BPM流程中心解决方案分享
  2. 通过dataGridView控件中的checkBox控件对数据库进行批量删除
  3. C++中颜色的设置
  4. Java 8开发的4大顶级技巧
  5. c# 代理IP获取通用方法
  6. Linux下Wireshark普通用户不能获取网络接口问题
  7. 第六周O题(等边三角形个数)
  8. shell中的path expansion
  9. pyqt 图片(label上显示
  10. java之jvm学习笔记二(类装载器的体系结构)
  11. web端常见安全漏洞测试结果分析-- appscan
  12. java内部类(转)
  13. Django实例
  14. 【c++】编译器为我们实现了几个类成员函数?
  15. 08 bash特性--shell脚本编程入门
  16. JVM总结-java基本类型
  17. Extjs4 store load 有中文字符提交后台乱码解决方法
  18. UML 中关系图的解说
  19. vue中实现中,自动补全功能
  20. 从swing分发线程机制上理解多线程[转载]

热门文章

  1. js函数相关高级用法
  2. dva 路由跳转
  3. OSG-HUD
  4. 【JAVA】关于java中 类.class.getResource(&quot;/&quot;).getPath()获取路径有空格的问题
  5. Linux命令应用大词典-第25章 备份与还原
  6. OpenMPI源码剖析2:ompi_mpi_errors_are_fatal_comm_handler函数
  7. 初步了解CUDA(零)
  8. Python中的Numeric
  9. c# dll问题
  10. 计算器软件实现系列(六)windowform窗体+SQL+策略模式