我的第一道斜率优化。

就这道题而言,写出原始的方程:

  dp[i] = min{ dp[j] + (sum[i]-sum[j])+ M | j in [0,i) }

O(n^2)的复杂度肯定超时,要么优化转移,要么重写方程。

斜率优化的思想就是减少不必要的枚举(即不枚举肯定不会成为决策点的j)。

我们考虑两个位置p<q<i

“选择q比选择p优” 当且仅当 dp[q]+(sum[i]-sum[q])2+M < dp[p]+(sum[i]-sum[p])2+M

化简右边即:

[ (dp[q]+sum2[q])-(dp[p]+sum2[p]) ] / ( sum[q]-sum[p] ) < sum[i]*2

该式可以看成两个点连线的斜率:( sum[q], dp[q]+sum2[q] ) 与 ( sum[p], dp[p]+sum2[p] ) 两点。

文字语言就是:“将每个决策位置看成一个二维坐标系下的点,对于两个决策点,后者比前者优 当且仅当 两点连线的斜率小于sum[i]*2”

这样怎么减少不必要的枚举呢?

可以发现,所有决策点一定是单调不下降的(题中可能出现权值为0,此时有可能出现斜率为正无穷,若M=0,还有可能出现重点,所以计算斜率不要用除法)

上面的B点一定是不会成为最优决策点的,反证法:

如果B成为最优决策点,那么

2*sum[i]>kab 且 2*sum[i]<kbc

而显然kab > kbc ,这样就推出了2*sum[i]>kab >kbc >2*sum[i],矛盾。

故B不可能成为最优决策点,同理,D也不行,删掉这些点后,我们剩下的图形就是一个下凸的图形了:

我们维护这样一个下凸的图形到队列中:

当要查找i位置的最优决策点时,一直删除队首的点,直到队中的第一条直线的斜率大于2*sum[i]或队中只有一个点,此时队首元素就是最优决策点。

计算完i位置后,要将i位置对应的点加入到队列中,此时会删除一些对尾的点,以保持队中点的下凸性(注意处理重合的点)。

这样,我们就利用斜率优化掉了很多不必要的枚举,将时间复杂度从O(n^2)降到了O(n)。

 #include <cstdio>
#define ln(A,B) ((B)-(A))
#define maxn 500010 typedef long long lng; struct Vector {
lng x, y;
int id;
Vector(){}
Vector( lng x, lng y, int id ) : x(x), y(y), id(id) {}
Vector operator-( const Vector & b ) const { return Vector(x-b.x,y-b.y,); }
lng operator&( const Vector & b ) const {
return x*b.y-y*b.x;
}
};
typedef Vector Point; int n, m;
int cost[maxn];
lng sum[maxn];
lng dp[maxn]; int beg, end;
Point qu[maxn]; int main() {
while( ) {
if( scanf( "%d%d", &n, &m )!= ) return ; sum[] = ;
for( int i=; i<=n; i++ ) {
scanf( "%d", cost+i );
sum[i] = sum[i-]+cost[i];
} dp[] = ;
qu[beg=end=] = Point( , , ); for( int i=; i<=n; i++ ) {
while( end>beg && qu[beg+].y-qu[beg].y<=(qu[beg+].x-qu[beg].x)**sum[i] )
beg++;
int j = qu[beg].id;
dp[i] = dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+m;
Point npt = Point( sum[i], dp[i]+sum[i]*sum[i], i );
while( end>beg && (ln(qu[end-],qu[end])&ln(qu[end-],npt))<= )
end--;
qu[++end] = npt;
}
printf( "%lld\n", dp[n] );
}
}

hdu 3507 斜率优化的更多相关文章

  1. Print Article HDU - 3507 -斜率优化DP

    思路 : 1,用一个单调队列来维护解集. 2,假设队列中从头到尾已经有元素a b c.那么当d要入队的时候,我们维护队列的下凸性质, 即如果g[d,c]<g[c,b],那么就将c点删除.直到找到 ...

  2. HDU 3507 斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  3. HDU 3507斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  4. HDU 3507 斜率优化 DP Print Article

    在kuangbin巨巨博客上学的. #include <iostream> #include <cstdio> #include <cstring> #includ ...

  5. hdu 3507 斜率dp

    不好理解,先多做几个再看 此题是很基础的斜率DP的入门题. 题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 设dp[i]表示输出前i个 ...

  6. hdu 3669(斜率优化DP)

    Cross the Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) ...

  7. HDU 4258 斜率优化dp

    Covered Walkway Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  8. HDU 2829 斜率优化DP Lawrence

    题意:n个数之间放m个障碍,分隔成m+1段.对于每段两两数相乘再求和,然后把这m+1个值加起来,让这个值最小. 设: d(i, j)表示前i个数之间放j个炸弹能得到的最小值 sum(i)为前缀和,co ...

  9. hdu 3045 斜率优化DP

    思路:dp[i]=dp[j]+sum[i]-sum[j]-(i-j)*num[j+1]; 然后就是比较斜率. 注意的时这里j+t<=i: #include<iostream> #in ...

随机推荐

  1. let块级作用域

    let是es6中新加的作用域,即块级作用域. var申明的变量要么全局,要么函数级,而let允许把变量的作用域限制在块级域中,这里的块级可以是()内,或{}内. 示例: code_1: "u ...

  2. java 1.8 新特性 stream

    并发提升 java 中Stream类似于hadoop中的数据分析的思路,只不过hadoop大,用的是多台机算机的计算生态,而java  stream使用的单台计算机中的多cpu分析一块数据的过程.通过 ...

  3. 005zabbix3.0报错记录

    一.问题描述 在zabbix_server添加变量时,出现了以下的报错,

  4. [写出来才有价值系列:node.js]node.js 02-,learnyounode

    安装learnyounode: npm install g learnyounode 官方说直接 但是我发现不行,很慢几乎就是死在那里了 还好有淘宝的东西给我们用https://npm.taobao. ...

  5. spring-mybatis.xml配置

    1.自动扫描 <context:component-scan base-package="com.javen" /> 2.引入配置文件 <bean id=&quo ...

  6. C语言实现int转换string

    #include <stdio.h> #include <stdlib.h> #include <string.h> int string2int(const ch ...

  7. 如何删除git远程分支(转)

    1,在开发过程中,大家在远程创建了许多分支,有些是无用的,该如何删除呢,可以参考下面的方法. 如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的 master 分支(或任何其他存放 稳 ...

  8. linux中getmntent setmntent endmntent 用法例子

    mntent 结构是在 <mntent.h> 中定义,如下:               struct mntent {                      char    *mnt ...

  9. linux下c图形化编程之gtk+2.0简单学习

    在linux下想做一个图形化的界面,然后自己选择使用gtk+2.0来进行编辑,我的电脑已经安装过gtk+2.0了,所以就在网上找了一个安装方法,结果未测试,大家有安装问题可以说下,一起探讨下. 1.安 ...

  10. Windows内核分析——内核调试机制的实现(NtCreateDebugObject、DbgkpPostFakeProcessCreateMessages、DbgkpPostFakeThreadMessages分析)

    本文主要分析内核中与调试相关的几个内核函数. 首先是NtCreateDebugObject函数,用于创建一个内核调试对象,分析程序可知,其实只是一层对ObCreateObject的封装,并初始化一些结 ...