我的第一道斜率优化。

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

  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. Linux下命令lrzsz

    lrzsz是什么 在使用Linux的过程中,难免少不了需要上传下载文件,比如往服务器上传一些war包之类的,之前都是使用winSCP,lrzsz是一个更方便的命令,可以直接在Linux中输入命令,弹出 ...

  2. [转载]Android中Bitmap和Drawable

    一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...

  3. 深入理解Spring系列之六:bean初始化

    转载 https://mp.weixin.qq.com/s/SmtqoELzBEdZLo8wsSvUdQ <深入理解Spring系列之四:BeanDefinition装载前奏曲>中提到,对 ...

  4. 【shell】shell编程(五)-读取参数

    通过前几篇文章的学习,我们学会了shell的基本语法.在linux的实际操作中,我们经常看到命令会有很多参数,例如:ls -al 等等,那么这个参数是怎么处理的呢? 接下来我们就来看看shell脚本对 ...

  5. Linux CentOS 6.9(图形界面)安装中文输入法

    安装步骤 1. 切换到 root 用户,执行 yum -y install "@Chinese Support" 2. 退出终端,选择桌面菜单中 "System" ...

  6. SPOJ JZPLIT

    Problem SPOJ Solution 考虑任意一个作为矩阵四个角的位置 \(r_i \oplus c_j\oplus a_{i,j}\oplus x_{i,j}=0\) \(r_i \oplus ...

  7. 122.Best Time to Buy and Sell Stock II---dp

    题目链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/ 题目大意:基本定义与121类似,不 ...

  8. FAQ1: 列表索引和切片问题

    问题1. 超过列表成员个数的索引访问列表会出现IndexError错误,但是如果用切片去访问就不会报错,而是返回一个空列表.同样元组也是. >>> a=[1,2,3,4] >& ...

  9. 1、CentOS 6 安装GitLab

    1.安装和配置必需的依赖项 在CentOS上将系统防火墙打开HTTP和SSH访问. sudo yum install -y curl policycoreutils-python openssh-se ...

  10. HDU 3533 Escape(BFS+预处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3533 题目大意:给你一张n* m的地图,人在起点在(0,0)要到达终点(n,m)有k(k<=10 ...