「HNOI2008」玩具装箱
传送门
Luogu
解题思路
\(\text{DP}\) 很显然:
设 \(dp_i\) 表示前 \(i\) 个玩具的最小费用,转移就是:
\(dp_i = \max\limits_{0\le j < i}\left\{dp_j+(i-j-1+s_i-s_j-L)^2\right\}\)
\(s_i=\sum_{j=1}^ic_j\),但这是 \(O(n^2)\) 的,显然不够优秀,考虑进一步优化。
我们可以化简一下这个式子:
假设 \(dp_i\) 成功从 \(dp_j\) 转移过来,那么就有:
\(dp_i=dp_j+(i-j-1+s_i-s_j-L)^2\)
整理一下式子:
设 \(a_i = s_i+i-L-1,b_i=s_i+i\)
那么就有:
\(dp_i=dp_j+(a_i-b_j)^2\)
展开并移项可得:
\(dp_j+b_j^2=2a_ib_j+dp_i-a_i^2\)
再设 \(x_i=2b_i,y_i=dp_i+b_i^2\)
\(y_j=a_ix_j+dp_i-a_i^2\)
又因为 \(a_i^2\) 是定值,要最小化 \(dp_i\) ,那么就相当于坐标系中一条斜率为 \(a_i\) 的经过点 \((x_j, y_j)\) ,使得它的纵截距最小化。
又因为我们的 \(a_i, b_i\) 都是递增的,显然这些可能的转移点都要在下凸壳上才能使截距最小。
所以我们用单调队列,维护一下凸包上的转移点。
当前最优转移点从队头不断弹出不最优的点,并用最后的合法情况转移 \(dp_i\)。
插入当前的 \(i\) 时,为了确保凸包的性质,先不断从队尾弹出不合法的点,再插入 \(i\)。
最后输出答案 \(dp_n\)。
细节注意事项
- 咕咕咕
参考代码
#include <algorithm>
#include <iostream>
#include <cstdio>
#define rg register
using namespace std;
typedef double db;
const int _ = 50010;
int n, L; db dp[_], s[_], A[_], B[_];
int hd = 1, tl = 1, Q[_];
inline db X(int i) { return (db) B[i]; }
inline db Y(int i) { return (db) dp[i] + B[i] * B[i]; }
inline db slope(int i, int j) { return (db) (Y(j) - Y(i)) / (X(j) - X(i)); }
int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
scanf("%d%d", &n, &L);
for (rg int i = 1; i <= n; ++i) scanf("%lf", s + i), s[i] += s[i - 1];
for (rg int i = 1; i <= n; ++i) A[i] = (db) s[i] + i - L - 1;
for (rg int i = 1; i <= n; ++i) B[i] = (db) s[i] + i;
for (rg int i = 1; i <= n; ++i) {
while (hd < tl && slope(Q[hd], Q[hd + 1]) < 2 * A[i]) ++hd;
dp[i] = dp[Q[hd]] + (A[i] - B[Q[hd]]) * (A[i] - B[Q[hd]]);
while (hd < tl && slope(Q[tl - 1], Q[tl]) > slope(Q[tl - 1], i)) --tl;
Q[++tl] = i;
}
printf("%lld\n", (long long) dp[n]);
return 0;
}
完结撒花 \(qwq\)
「HNOI2008」玩具装箱的更多相关文章
- 【BZOJ1010】【HNOI2008】玩具装箱(斜率优化,动态规划)
[BZOJ1010][HNOI2008]玩具装箱 题面 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一 ...
- 【BZOJ】【1010】【HNOI2008】玩具装箱Toy
DP/斜率优化 根据题目描述很容易列出动规方程:$$ f[i]=min\{ f[j]+(s[i]-s[j]+i-j-1-L)^2 \}$$ 其中 $$s[i]=\sum_{k=1}^{i} c[k] ...
- BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1010 给出\(n\)和\(l\).有\(n\)个玩具,第\(i\)个玩具的长度是\(c[i]\ ...
- 动态规划(斜率优化):BZOJ 1010 【HNOI2008】 玩具装箱
玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 8218 Solved: 3233[Submit] Description P 教授要去 ...
- BZOJ 1010 【HNOI2008】 玩具装箱toy
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...
- 【BZOJ1010】【HNOI2008】玩具装箱
继续看黄学长代码 原题: P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1.. ...
- BZOJ 1010 [HNOI2008]toy 玩具装箱
2017.6.9:经过我的不懈努力,终于把此题A掉了,但上凸和下凸总是那么让人费解…… P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意 ...
- 【HNOI2008】玩具装箱TOY & 斜率优化学习笔记
题目 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为 \(1\cdots N\ ...
- 【HNOI2008】玩具装箱
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具 ...
随机推荐
- Python中Numpy.nonzero()函数
Numpy.nonzero()返回的是数组中,非零元素的位置.如果是二维数组就是描述非零元素在几行几列,三维数组则是描述非零元素在第几组中的第几行第几列. 举例如下: 二维数组: a = np.arr ...
- idea 创建maven子父工程
1.创建maven工程: 2. 创建工程名称: 3.删除父工程下的src文件夹,指定打包方式为pom,添加maven依赖: 4.右键项目添加子工程: 5.添加子工程名称: 6.子工程创建成功: 7.依 ...
- ➡️➡️➡️IELTS speaking by simon
目录 p1 课程概述 p2 speaking part1, intro, warm up introduction questions then 4 questions about one topic ...
- 短信通道——阿里大鱼(java)
综述 注:本文写于2017年6月22日升级之后. 使用阿里大鱼发送短信已经成为一种趋势,因为权威,而且价格也比较适中,被越来越多的公司所采用.在介绍阿里大鱼发送短信之前,首先得拥 ...
- JavaScript高级特征之面向对象笔记二
Prototype 1. 当声明一个函数的时候,浏览器会自动为该函数添加一个属性prototype, 2. 该属性的默认值为{} 3. 可以动态的给prototype增加key和value值 4 ...
- P1017进制转化
P1017进制转化 也不知道为啥,这么简单的题困扰了我这么长时间 #include<cstdio> using namespace std; int m; //被除数= 除数*商 + 余数 ...
- spring boot 中的配置文件可以存放的位置
- 前端代码编译器Hbuilder下载地址和谷歌浏览器下载地址
编译器:HbuilderX 浏览器:谷歌浏览器
- 认识gets&read(buffer over flow is bof)
gets不会检查输入的长度,从而有数据覆盖的风险,
- 列举出给定数量的字符的所有组成情况-java实现
老早以前刚学程序的时候碰到了这么个问题,当时没想出来,今天突然想起来了这么个问题于是写了下,也算留个纪念吧 public static String itr; public static void m ...