斜率优化板题 HDU 3507 Print Article
- 题目大意:输出N个数字a[N],输出的时候可以连续的输出,每连续输出一串,它的费用是 “这串数字和的平方加上一个常数M”。n<=500000
- 我们设dp[i]表示输出到i的时候最少的花费,sum[i]表示从a[1]到a[i]的数字和。于是方程就是: dp[i]=dp[j]+M+(sum[i]-sum[j])^2;
- 很显然这个是一个二维的。题目的数字有500000个,不用试了,二维铁定超时了。那我们就来试试斜率优化吧,看看是如何做到从O(n^2)复杂度降到O(n)的。
- 我们假设k<j<i。如果在j的时候决策要比在k的时候决策好,那么也是就是dp[j]+M+(sum[i]−sum[j])2<=dp[k]+M+(sum[i]−sum[k])2dp[j]+M+(sum[i]-sum[j])^2 <= dp[k]+M+(sum[i]-sum[k])^2dp[j]+M+(sum[i]−sum[j])2<=dp[k]+M+(sum[i]−sum[k])2。(因为是最小花费嘛,所以优就是小于)
- 两边移项一下,得到:
(dp[j]+sum[j]2)−(dp[k]+sum[k]2)<=(sum[j]−sum[k])∗2∗sum[i](dp[j]+sum[j]^2)-(dp[k]+sum[k]^2) <= (sum[j]-sum[k])*2*sum[i](dp[j]+sum[j]2)−(dp[k]+sum[k]2)<=(sum[j]−sum[k])∗2∗sum[i]
将(sum[j]−sum[k])(sum[j]-sum[k])(sum[j]−sum[k])除过去,得到:
[(dp[j]+sum[j]2)−(dp[k]+sum[k]2)]/(sum[j]−sum[k])<=2∗sum[i][(dp[j]+sum[j]^2)-(dp[k]+sum[k]^2)]/(sum[j]-sum[k]) <= 2*sum[i][(dp[j]+sum[j]2)−(dp[k]+sum[k]2)]/(sum[j]−sum[k])<=2∗sum[i] - 令xxxi =dp[i]−sum[i]= dp[i]-sum[i]=dp[i]−sum[i]2, yyyi =2∗sum[i]= 2*sum[i]=2∗sum[i].
那么不就是yyyj−y-y−yk/x/x/xj−x-x−xk<=2∗sum[i]<=2*sum[i]<=2∗sum[i]么? 左边是不是斜率的表示?
那么(y(y(yj−y-y−yk)/(x)/(x)/(xj−x-x−xk)<=2∗sum[i])<=2*sum[i])<=2∗sum[i]说明了什么呢?
说明k[j,k]=(yk[j,k]=(yk[j,k]=(yj−y-y−yk)/(x)/(x)/(xj−x-x−xk)<=2∗sum[i])<=2*sum[i])<=2∗sum[i]代表这j的决策比k的决策要更优。 - 关键的来了:若k<j<ik<j<ik<j<i且k[i,j]<k[j,k]k[i,j]<k[j,k]k[i,j]<k[j,k],则j点永远不可能成为最优解,可以直接将它踢出我们的最优解集。为什么呢?
分三种情况讨论:
设当前点为a
1.如果k[i,j]k[i,j]k[i,j]与k[j,k]k[j,k]k[j,k]均小于2∗sum[a]2*sum[a]2∗sum[a],则i比j优,j比k优
2.如果k[i,j]k[i,j]k[i,j]与k[j,k]k[j,k]k[j,k]均大于2∗sum[a]2*sum[a]2∗sum[a],则k比j优,j比i优
3.如果k[i,j]<sum[a]k[i,j]<sum[a]k[i,j]<sum[a]且k[i,j]>2∗sum[a]k[i,j]>2*sum[a]k[i,j]>2∗sum[a],则i比j优,k比j优
不论如何,j都无法成为最佳决策点,所以可以排除j
于是,所有的决策点满足一个下凸包性质 - 接下来看看如何找最优解。 设k<j<ik<j<ik<j<i。
由于我们排除了k[i,j]<k[j,k]k[i,j]<k[j,k]k[i,j]<k[j,k]的情况,所以整个有效点集呈现一种下凸性质,即k[i,j]>k[j,k]k[i,j]>k[j,k]k[i,j]>k[j,k]。
这样,从左到右,斜率之间就是单调递增的了。当我们的最优解取得在j点的时候,那么k点不可能再取得比j点更优的解了,于是k点也可以排除。换句话说,j点之前的点全部不可能再比j点更优了,可以全部从解集中排除。

- 于是对于这题我们对于斜率优化做法可以总结如下:
1.用一个单调队列来维护解集。
2.假设队列中从头到尾已经有元素a b c。那么当d要入队的时候,我们维护队列的下凸性质,即如果k[d,c]<=k[c,b]k[d,c]<=k[c,b]k[d,c]<=k[c,b],那么就将c点删除。直到找到k[d,x]>k[x,y]k[d,x]>k[x,y]k[d,x]>k[x,y]为止,并将d点加入在该位置中。
3.找最佳决策点时,设当前求解状态为i,从队头开始,如果已有元素a b c,当i点要求解时,如果k[b,a]<=2∗sum[i]k[b,a]<=2*sum[i]k[b,a]<=2∗sum[i],那么说明b点比a点更优,a点可以排除,于是a出队,直到第一次遇到k[j,j−1]>2∗sum[i]k[j,j-1]>2*sum[i]k[j,j−1]>2∗sum[i],此时j-1即为最佳决策点。

参考代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 500005;
int n, m, s, t, dq[MAXN];
int sum[MAXN], f[MAXN];
inline int Getup(int i, int j) { return f[i] + sum[i]*sum[i] - f[j] - sum[j]*sum[j]; } //Yi-Yj
inline int Getdown(int i, int j) { return sum[i] - sum[j]; } //Xi-Xj
int main ()
{
int x;
while(scanf("%d%d", &n, &m) == 2)
{
for(int i = 1; i <= n; i++) scanf("%d", &x), sum[i] = sum[i-1] + x;
f[0] = 0; s = t = 0; dq[t++] = 0;
for(int i = 1; i <= n; i++)
{
while(t-s > 1 && Getup(dq[s+1], dq[s]) <= sum[i] * 2 * Getdown(dq[s+1], dq[s])) s++;
f[i] = f[dq[s]] + (sum[i] - sum[dq[s]]) * (sum[i] - sum[dq[s]]) + m;
while(t-s > 1 && Getup(i, dq[t-1]) * Getdown(dq[t-1], dq[t-2]) <= Getup(dq[t-1], dq[t-2]) * Getdown(i, dq[t-1])) t--;
dq[t++] = i;
}
printf("%d\n", f[n]);
}
}
斜率优化板题 HDU 3507 Print Article的更多相关文章
- hdu 3507 Print Article(斜率优化DP)
题目链接:hdu 3507 Print Article 题意: 每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值 题解: 设dp[i]表示前i个字符需要消耗的 ...
- HDU 3507 Print Article 斜率优化
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU 3507 Print Article(DP+斜率优化)
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) ...
- DP(斜率优化):HDU 3507 Print Article
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU 3507 Print Article(斜率优化推导)
$dp$,斜率优化. 第一次做斜率优化的题目,看了一些题解,自己总结一下. 这题是说有$n$个数字,可以切成任意段,每一段的费用是这一段数字的和平方加上$M$.问最小费用是多少. 设$dp[i]$为$ ...
- HDU 3507 Print Article(斜率优化DP)
题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...
- HDU 3507 Print Article(斜率优化)
显然的斜率优化模型 但是单调队列维护斜率单调性的时候出现了莫名的锅orz 代码 #include <cstdio> #include <algorithm> #include ...
- HDU 3507 [Print Article]DP斜率优化
题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...
- HDU 3507 - Print Article - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 Zero has an old printer that doesn't work well s ...
随机推荐
- springboot异步线程
前言 最近项目中出现了一个问题,发现自己的定时器任务在线上没有执行,但是在线下测试时却能执行,最后谷歌到了这篇文章SpringBoot踩坑日记-定时任务不定时了?; 本篇文章主要以自己在项目中遇到的问 ...
- Codeforces Round #603 (Div. 2) (题解)
A. Sweet Problem (找规律) 题目链接 大致思路: 有一点瞎猜的,首先排一个序, \(a_1>a_2>a_3\) ,发现如果 \(a_1>=a_2+a_3\) ,那么 ...
- Docker 封装java镜像
一.概述 目前java采用的框架是Spring,服务器直接通过 java -jar xxx.jar 就可以启动服务了. 二.jdk镜像 在docker中跑java应用,需要有jdk环境支持才行. 获取 ...
- JavaScript 的 深拷贝和浅拷贝
深拷贝和浅拷贝都是针对的引用类型, JS中的变量类型分为值类型(基本类型)和引用类型: 对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会对地址进行拷贝,最终两个变量指向同一份数据 一.先 ...
- 《JAVA高并发编程详解》-wait和sleep
- nodejs的交互式解释器模式常用命令
node - 进入交互器交互器解释模式 ctrl + c - 退出当前终端 ctrl + c 按下两次 - 退出 Node REPL ctrl + d - 退出 Node REPL 向上/向下 键 - ...
- C# vb .net实现博物馆哑色框架特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的博物馆哑色框架效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授 ...
- mysql存储过程简单例子
1.之前经常在oracle数据库中使用存储过程,换到mysql后用的不多,但是有时候也用,大致记录一下,基本和oracle的一样. CREATE DEFINER = `root`@`%` PROCED ...
- 2019 用友网络java面试笔试题 (含面试题解析)
本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条. 用友网络等公司offer,岗位是Java后端开发,最终选择去了 用友网络. 面试了很多家公司,感觉大部分公司考察 ...
- Linux下which、whereis、locate、find命令作用
1 which 查看可执行文件的位置,也可以找到命令别名 2 whereis 查看文件的位置 3 locate 系统数据库查找文件位置,数据库大约每天更新一次 4 find 根据查找条件,搜寻硬盘查询 ...