HDU -3507 Print Article(斜率优化)
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 this degree.
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
There are many test cases. For each test case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines. Input are terminated by EOF.
Output
A single number, meaning the mininum cost to print the article.
Sample Input
5 5
5
9
5
7
5
Sample Output
230
第一道斜率优化题,对于边界的处理还要注意,看了很多dalao的代码才写完..
主要就是利用单调队列维护一个下凸包,具体推导过程网上的题解也都很清晰...我的都在纸上而且字太丑了
代码
#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PLL;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 500010;
const ll MAXM = 5e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int dp[MAXN];
int q[MAXN];
int sum[MAXN];
int head, tail, n, m;
//dp[i]=min(dp[j]+(sum[i]-sum[j])^2)
int Getdp(int i, int j)
{
return dp[j] + m + (sum[i] - sum[j]) * (sum[i] - sum[j]);
}
int Getup(int j, int k)
{
return dp[j] + sum[j] * sum[j] - (dp[k] + sum[k] * sum[k]);
}
int Getdown(int j, int k)
{
return sum[j] - sum[k];
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
dp[0] = 0;
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
sum[i] = sum[i - 1] + x;
}
head = tail = 0;
q[tail++] = 0;
//单调队列维护下凸包
for (int i = 1; i <= n; i++)
{
while (head + 1 < tail && Getup(q[head + 1], q[head]) <= 2 * sum[i] * Getdown(q[head + 1], q[head]))
head++;
dp[i] = Getdp(i, q[head]);
while (head + 1 < tail && Getup(i, q[tail - 1]) * Getdown(q[tail - 1], q[tail - 2]) <= Getup(q[tail - 1], q[tail - 2]) * Getdown(i, q[tail - 1]))
tail--;
q[tail++] = i;
}
printf("%d\n", dp[n]);
}
return 0;
}
原文地址:https://www.cnblogs.com/graytido/p/11714022.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android自定义View实现抖音飘动红心效果
- Android Studio 利用Splash制作APP启动界面的方法
- android surfaceView实现播放视频功能
- Android Studio中一套代码多渠道打包的实现方法
- Android自定义View实现圆环进度条
- Android启动页用户相关政策弹框的实现代码
- 10个好用的 HTML5 特性
- Android实现签名涂鸦手写板
- Android 开发使用Activity实现加载等待界面功能示例
- 详解Android使用CoordinatorLayout+AppBarLayout+CollapsingToolbarLayou实现手指滑动效果
- Android开发自定义控件之折线图实现方法详解
- Android Studio实现长方体表面积计算器
- android studio实现简单的计算器功能
- Android小程序实现个人信息管理系统
- Flutter 使用Navigator进行局部跳转页面的方法