HDU 3507 Print Article (斜率优化)

HDU 3507 Print Article (斜率优化)

ACM

题目地址:

HDU 3507 Print Article

题意:

给定一个长度为n的序列,和一个常数m,我们可以将序列分成随意段,每段的权值为sum(arr[i]) + C(x<=i<=y),求一种划分方法使得整个序列的权值最小

分析:

from:亟隐‘s blog

f[i]=min(f[k]+(sum(i)-sum(k))^2 )+m

= f[k]+sum^2(i)+sum^2(k)-2*sum(i)*sum(k)+m.

也就是找一个最小的f[k]+sum^2(k)-2*sum(i)*sum(k),如果k优于j,必有(f[k]+sum^2(k)-f[j]-sum^2(j))/(2*sum(k)-2*sum(j))<=s[i].

代码:

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        3507.cpp
*  Create Date: 2014-09-19 10:19:57
*  Descripton:  dp
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;

const int N = 5e6 + 10;

int n, m, l, r, q[N];
ll s[N], x[N], y[N], k[N];

void init() {
	int x;
	repf (i, 1, n) {
		cin >> x;
		s[i] = s[i - 1] + x;
		k[i] = s[i] * 2;
	}
}

inline bool check(int a, int b, int c) {
	return (y[a] - y[b]) * (k[b] - k[c]) <= (y[b] - y[c]) * (k[a] - k[b]);
}

void solve() {
	q[0] = l = r = 0;
	repf (i, 1, n) {
		while (l < r && (y[q[l+1]]-y[q[l]]) <= s[i] * (k[q[l+1]]-k[q[l]]))
			l++;
		x[i] = x[q[l]] + (s[i] - s[q[l]]) * (s[i] - s[q[l]]) + m;
		y[i] = x[i] + s[i] * s[i];
		while (l < r && check(i, q[r], q[r-1]))
			r--;
		q[++r] = i;
	}
	cout << x[n] << endl;
}

int main() {
	ios_base::sync_with_stdio(0);
	while (cin >> n >> m) {
		init();
		solve();
	}
	return 0;
}
时间: 2024-08-25 22:15:25

HDU 3507 Print Article (斜率优化)的相关文章

HDU 3507 Print Article 斜率优化

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4810    Accepted Submission(s): 1451 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

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 即 f[j] + s[j]*s[j] = 2*s[i]*s[j] + f[i] - s[i]*s[i] - m 于是维护下凸包即可: 写成 double 的 slp 总是不对,把分母乘到对面就对了... 代码如下: #include<iostream> #include<cstdio>

HDU 3507 Print Article (斜率DP)

题意:要输出N个数字a[N],输出的时候可以连续连续的输出,每连续输出一串,它的费用是 "这串数字和的平方加上一个常数M". 析:这个题很容易想到DP方程dp[i] = min{dp[j] + M + (sum[i]-sum[j])^2},但是很明显是O(n^2),TLE是必然的,所以要进行优化. 假设 i > j > k ,并且 j 要比 k 好,那么就是 dp[j] + M + (sum[i]-sum[j])^2 < dp[k] + M + (sum[i]-sum

HDU 3507 单调队列 斜率优化

斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方法来做,但是该题要求的是区间和的平方,于是要转换单调的计算方法为斜率,也就是凸线. 其他就是最基本的单调DP /** @Date : 2017-09-04 15:39:05 * @FileName: HDU 3507 单调队列 斜率优化 DP.cpp * @Platform: Windows * @

斜率优化dp简讲 &amp;&amp; HDU 3507 Print Article

Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate t

DP(斜率优化):HDU 3507 Print Article

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 8199    Accepted Submission(s): 2549 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

HDU 3507 Print Article(DP+斜率优化)

 Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7960    Accepted Submission(s): 2465 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiq

HDU 3507 Print Article(斜率优化)

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 15536    Accepted Submission(s): 4813 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiqu

HDU 3507 Print Article(斜率DP优化)

Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate t