「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件玩具 ...
随机推荐
- cf 76 div2
传送门 题意 t组样例 n个学生, x最多交换次数 a交换的第一个位置 b交换的第二个位置 最多是交换n-1次,不懂的话可以找个数列自己模拟一下: 然后其他的就是abs(a-b)+x;两个位置之间的距 ...
- stackADT
stack.h #ifndef STACK_H_INCLUDED #define STACK_H_INCLUDED #include <stdbool.h> typedef struct ...
- 【Python矩阵及其基础操作】【numpy matrix】
一.矩阵生成 1.numpy.matrix: import numpy as np x = np.matrix([ [1, 2, 3],[4, 5, 6] ]) y = np.matrix( [1, ...
- css3 :default应用场景
引用自 张鑫旭文章.
- 2019最新整理JAVA面试题附答案
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- C/C++ scanf和gets 区别 , printf和puts区别
ref 1. scanf和gets区别 | 博客园 2. printf和puts区别 | CSDN scanf和gets都能从输入流stdin读取字符串,那么它们有什么区别呢? scanf 留回车:开 ...
- Struts+Spring+Hibernate整合笔记一
OpenSessionInview: 1.如果当前方法没有事物环境,则调用完毕getHibernate以后.session关闭: 说明:1如果测试dao层,没有事物环境 2如果测试service层,但 ...
- PCSearch需要管理员权限,开机自启
1.添加Windows服务,并设为自动启动: 2.通过服务启动AutoStartSevice.exe,通过AutoStartSevice.exe运行AutoStart.bat,通过AutoStart. ...
- Educational Codeforces Round 73 (Rated for Div. 2)E(思维,博弈)
//这道题博弈的核心就是不能让后手有一段只能放b而长度不够放a的段,并且先手要放最后一次#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h> ...
- css中class后面跟两个类,这两个类用空格隔开
css中class后面跟两个类,这两个类用空格隔开,那么这两个类对这个元素都起作用,如果产生冲突,那么后面的类将替代前面的类.