[HDU 3507]Print Article
Description
One day Zero want to print an article which has
N words, and each word i has a cost Ci to be printed. Also, Zero know
that print k words in one line will cost
M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly.
Input
Output
Sample Input
Sample Output
题目大意
将一个序列分为若干段,每段代价为该段和平方+常数M,求代价和最小。
题解
斜率优化$DP$。
考虑朴素的做法,我们令$f[i]$表示前$i$位的最小代价和。
显然我们有转移方程:
f[i]=f[j]+sqr(sum[i]-sum[j])+m; //j>0&&j<i,sum[i]=∑a[i]
显然这是一个$O(n^2)$的做法,对于$500000$的数据肯定过不去。
可以发现,我们枚举每个$i$时会不断重复遍历相同的元素,显然冗余的遍历是可以略去的。
用数据结构优化,为了找到最值,我们容易想到单调队列。
由刚才那个式子,我们拆开:
f[i]=f[j]+sqr(sum[i]-sum[j])+m
<=>f[i]=f[j]+sqr(sum[i])+sqr(sum[j])-*sum[i]*sum[j]+m
<=>f[i]= f[j]+sqr(sum[j])+m +sqr(sum[i])-*sum[i]*sum[j] (*)
我们发现$(*)$式的右边的前面一个部分是与$i$无关的,可是后面一个部分,即
-*sum[i]*sum[j]
中的$i$,$j$杂糅在了一起,显然普通的单调队列行不通了。
我们令$k<j<i$,假设计算$f[i]$时,$j$处的值比$k$处优,显然我们会有:
f[j]+sqr(sum[i]-sum[j])+M <= f[k]+sqr(sum[i]-sum[k])+M;
拆开,化简:
((f[j]+sum[j]*sum[j])-(f[k]+sum[k]*sum[k])) / (sum[j]-sum[k]) <=sum[i]
这时,我们发现,式子只有右边与$i$有关了,我们可以考虑拿左边的部分放到队列里面。
我们不妨令
yj=(f[j]+sum[j]*sum[j]),yk=(f[k]+sum[k]*sum[k]),xj=*sum[j],xk=*sum[k]
Δy=yj-yk,Δx=xj-xk
那么就变成了斜率表达式:
Δy/Δx <= sum[i];
而且不等式右边是递增的。
所以我们可以看出以下两点:我们令
g[k,j]=Δy/Δx
第一:如果上面的不等式成立,那就说$j$比$k$优,而且随着$i$的增大上述不等式一定是成立的,也就是对$i$以后算$DP$值时,j都比k优。那么$k$就是可以淘汰的。
第二:如果,$k<j<i$,而且$g[k,j]>g[j,i]$那么$j$是可以淘汰的。
假设:$g[j,i]<sum[i]$就是$i$比$j$优,那么$j$没有存在的价值
相反如果:$g[j,i]>sum[i]$,那么同样有,$g[k,j]>sum[i]$ ,那么$k$比$j$优那么$j$是可以淘汰的,所以这样相当于在维护一个下凸的图形,斜率在逐渐增大。
通过一个单调队列来维护下凸壳。
#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define RE register
#define IL inline
#define sqr(x) (x*x)
#define deltax(j,k) (2*(sum[j]-sum[k]))
#define deltay(j,k) ((f[j]+sqr(sum[j]))-(f[k]+sqr(sum[k])))
using namespace std;
const int N=; IL int Read(); int n,m;
int sum[N+];
int q[N+],head,tail;
int f[N+]; int main()
{
while (~scanf("%d%d",&n,&m))
{
for (RE int i=;i<=n;i++) sum[i]=sum[i-]+Read(),f[i]=;
head=tail=;
q[tail++]=;
for (RE int i=;i<=n;i++)
{
while (head<tail-)
if (deltay(q[head+],q[head])<=sum[i]*deltax(q[head+],q[head])) head++;
else break;
int x=sum[i]-sum[q[head]];
f[i]=f[q[head]]+sqr(x)+m;
while (head<tail-)
if (deltay(q[tail-],q[tail-])*deltax(i,q[tail-])>=deltax(q[tail-],q[tail-])*deltay(i,q[tail-])) tail--;
else break;
q[tail++]=i;
}
printf("%d\n",f[n]);
}
return ;
} IL int Read()
{
int sum=;
char c=getchar();
while (c<''||c>'') c=getchar();
while (c>=''&&c<='') sum=sum*+c-'',c=getchar();
return sum;
}
[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]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 Zero has an old printer that doesn't work well s ...
- HDU 3507 Print Article(CDQ分治+分治DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3507 [题目大意] 将长度为n的数列分段,最小化每段和的平方和. [题解] 根据题目很容易得到dp ...
- ●HDU 3507 Print Article
题链: http://acm.hdu.edu.cn/showproblem.php?pid=3507 题解: 斜率优化DP 一个入门题,就不给题解了,网上的好讲解很多的. 这里就只提一个小问题吧( ...
- hdu 3507 Print Article —— 斜率优化DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507 设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m ...
- HDU 3507 Print Article(斜率优化DP)
题目链接 题意 : 一篇文章有n个单词,如果每行打印k个单词,那这行的花费是,问你怎么安排能够得到最小花费,输出最小花费. 思路 : 一开始想的简单了以为是背包,后来才知道是斜率优化DP,然后看了网上 ...
随机推荐
- Python多线程案例
from time import ctime,sleep import threading def music(): for i in range(2): print ("I was lis ...
- display属性
display 属性规定元素应该生成的框的类型. 值 描述 none 此元素不会被显示. block 此元素将显示为块级元素,此元素前后会带有换行符. inline 默认.此元素会被显示为内联元素,元 ...
- javascript 腾讯ABS云平台面试题及面试经历
既然说到面试前端肯定是Javascript各种问,只好各种答. 面试题肯定离不了,最近热门的Vue.js,React.js,Angular.js,Gulp,Webpack还有各种Js问题,还有令人头痛 ...
- day-5 python协程与I/O编程深入浅出
基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1. 什么是协程(以下内容来自维基百 ...
- 【编程开发】PHP---面向对象
面向对象编程 类:在现实世界中,任何事物都有种类的概念:车 类是由特征和行为构成的. 特征:都是不动的,从出厂的时候就已经内置好了(属性) 行为:一种动的状态.(方法(函数)) 行为依赖于这些特征,而 ...
- sql2008r2,以前好好可以用的,但装了vs2017后,连接不上了,服务也停了,结果手动也 启动不了, 无法加载或初始化请求的服务提供程
日志: 2017-12-14 12:33:17.53 服务器 A self-generated certificate was successfully loaded for encryption.2 ...
- rsync 自动创建目录的坑点
rsync同步文件有三种模式: 1.把源站路径下某个文件,同步到目标路径.例如rsync -aR /data/1/2/3/a.txt 1.1.1.1:/data/ ,目标机器将自动创建多层目录存放a. ...
- 作业五:RE 模块模拟计算器
# !/usr/bin/env python3 # _*_coding:utf-8_*_ ''' 实现模拟计算器的功能: 公式: - * ( (- +(-/) * (-*/ + /*/* + * / ...
- 用javascript做别踩白块游戏1
初学Javascript做的一个别踩白块小游戏,代码简陋,如下: <!DOCTYPE html> <html> <head> <!-- 禁用缩放功能 --&g ...
- redis入门(06)各种类型的操作命令
Redis 字符串命令下表列出了常用的 redis 字符串命令:序号 命令及描述1 SET key value 设置指定 key 的值2 GET key 获取指定 key 的值.3 GETRANGE ...