我的第一道斜率优化。

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

  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. NYOJ 133 子序列 (离散化)

    题目链接 描述 给定一个序列,请你求出该序列的一个连续的子序列,使原串中出现的所有元素皆在该子序列中出现过至少1次. 如2 8 8 8 1 1,所求子串就是2 8 8 8 1. 输入 第一行输入一个整 ...

  2. CDN基础详解

    什么是 CDN?     Origin Server: 源站,也就是做 CDN 之前的客户真正的服务器;   User: 访问者,也就是要访问网站的网民;   Edge Server: CDN 的服务 ...

  3. php审计学习:xdcms2.0.8注入

    注入点Fields: 注册页面会引用如下方法: $fields 变量是从 $fields=$_POST['fields']; 这里获取, 在代码里没有过滤. 打印 fields 数据查看: 从代码上看 ...

  4. Nginx实现404页面的几种方法【转】

    一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有以下集中配置方式,一起来看看. 第一种:Nginx自己的错误页面 Nginx访问一个静态的html 页面,当这个页面没 ...

  5. tomcat+ngnix单机搭建集群及端口占用问题

    1.将tomcat复制两份,如下: 2.新建环境变量,如下: 3.修改其中一个的配置文件,另一个保持不变,修改server.xml配置文件如下: <Server port="9005& ...

  6. Linux硬链接和软连接的区别与总结

    图示软硬链接的区别 有关硬链接的总结 具有相同inode节点号的多个文件互为硬链接文件: 删除硬链接文件或者删除源文件任意之一,文件实体并未被删除: 只有删除了源文件和所有对应的硬链接文件,文件实体才 ...

  7. 一个设置为display:none;的div,在用.height()方法获取不到它的高,获取到的高度为0.

    <div style="width:100px;height:100px;background:red;visibility:hidden"></div>/ ...

  8. POJ 2349 Arctic Network(最小生成树+求第k大边)

    题目链接:http://poj.org/problem?id=2349 题目大意:有n个前哨,和s个卫星通讯装置,任何两个装了卫星通讯装置的前哨都可以通过卫星进行通信,而不管他们的位置. 否则,只有两 ...

  9. Python+Selenium 自动化实现实例-数据驱动实例

    #coding=utf-8 from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) ...

  10. 仿微信小红圈消息提示App消息红圆点提示

    代码: <div class="wrap"> <div class="img"></div> <div class=& ...