斜率优化板题 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 ...
随机推荐
- MyBatis 学习笔记(七)批量插入ExecutorType.BATCH效率对比
MyBatis 学习笔记(七)批量插入ExecutorType.BATCH效率对比一.在mybatis中ExecutorType的使用1.Mybatis内置的ExecutorType有3种,默认的是s ...
- C语言:求π
1835: 圆的面积 本题的关键在于如何求π: 今天先给给大家介绍一种针对本题的方法——利用反三角函数求π. 在高数中arcsin(0)=arccos(1)=π,不过编译器中并没有arcsin和arc ...
- Rust 智能指针(二)
1. Rc<T> 引用计数指针 Rc<T> 是引用计数指针,可以使用clone使得指针所指向的数据具有多个所有者. enum List { Cons(i32, Rc<Li ...
- java之mybatis之动态sql
1. if 判读条件是否满足,满足将会把 sql 语句加上. <select id="findUser" parameterType="Map" resu ...
- 1014 福尔摩斯的约会(C#)
一.题目内容: 大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm.大侦探很快就 ...
- js文本对象模型[DOM]【续】(Node节点类型)
一.Document类型 document实例1.常用的一些属性documentElement 始终指向HTML页面中的<html>元素.body 直接指向<body>元 ...
- js对象的深入理解(六)
一.对象的创建(四种模式)1.工厂模式工厂模式示例: function createPerson(name,age){ var obj = { name:name, age:age, sayName: ...
- Java 单文件、多文件上传 / 实现上传进度条
博客地址:https://ainyi.com/76 日常,工作 在这里总结一下上传吧(是以前做过的练习,就汇总到个人博客吧) java ssm 框架实现文件上传 实现:单文件上传.多文件上传(单选和多 ...
- map put相同的key
Map添加相同的key 2018年09月09日 10:37:12 Airport_Le 阅读数:6479 HashMap是的key是不能重复的,如果有相同的key,最后一个key对应的value会 ...
- Oracle UNDO块
过程:开始一个事务--通过事务信息找到UNDO块头的所在的段名及数据文件号等--转储UNDO header--在事务表中对应槽位找到前镜像dba--转储数据块--找到对应记录得到bdba--转储数据块 ...