题目传送门

记 \(f[i]\) 表示装好前 \(i\) 个的最小花费。容易写出转移:

\[f[i] = \min_{j \lt i} \ [f[j]+(s[i] - s[j] - 1 - L) ^ 2]
\]

直接转移是 \(O(n ^ 2)\) 的,我们考虑斜率优化。

斜率优化的过程

(一)问题转化成了求最小截距。

我们把 \(min\) 的外壳去掉,并且提前把 \(L +1\) (式子更简洁) 可以得到:

\[f[i] = f[j]+(s[i] - s[j] - 1 - L) ^ 2
\]

把括号打开,可以得到:

\[f[i] = f[j] + s[i] ^ 2 - 2\times s[i] \times L - 2 \times s[i] \times s[j] + (s[j] + L) ^ 2
\]

移项后得到:

\[(2s[i]) \times s[j] + (f[i] - s[i] ^ 2 + 2 \times s[i] \times L) = f[j] + (s[j] +L) ^ 2
\]

此时,如果我们把这看做一个一次函数,那么

\[k = 2s[i]\\
x = s[j]\\
b = (f[i] - s[i] ^ 2 + 2 \times s[i] \times L)\\
y = f[j] + (s[j] +L) ^ 2
\]

注意到固定 \(i\) 后,\(k\) 是固定的。而对于每个 \(j\), 我们都可求出对应的 \((x, y)\)。此时当 \(b\) 最小时,\(f[i]\) 也会最小。

(二)截距在哪里最小?(图像理解)

我们知道有用的 \(j\) 在二维平面上形成的点阵是个凸包。

我们惊讶的发现斜率竟然是固定的!我们可以平移这条直线至与凸包相切,显然这个切点 \(E\), 就对应着最小的截距。

怎么找这个点呢?发现 \(E\) 点以前的斜率都小于当前 \(k\), \(E\) 点之后的斜率都大于等于 \(k\), 因此可以二分这个位置。时间复杂度 \(O(nlogn)\)。

(三)决策单调性的优化(图像理解)

决策单调性的定义:

设 \(j_0[i]\) 表示 \(f[i]\) 转移的最优决策点,那么 决策单调性 可以描述为 \(\forall i \le i'\), \(j_0[i] \le j_0[i']\)。即随着 \(i\) 递增,所找到的 最优决策点 是递增态(非严格递增)。

发现 \(k = 2s[i]\), 而 \(s[i]\) 是前缀和,显然是递增的,那么我们的决策点也一定会越来越大(因为目标斜率递增)

详细证明参见参考博客。

用单调队列维护凸包的点集,分三步:

  1. 将斜率比目标斜率小的点弹出, 在队首位置找到最优决策点 \(j\)。
  2. 用最优决策点 \(j\) 更新 \(dp[i]\)。
  3. 把新的点加入队列中。

时间复杂度 \(O(n)\)。

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
#define int ll
using namespace std;
using ll = long long;
const int N = 1e5 + 5;
int L, n, h = 1, t = 0;
int f[N], s[N], q[N];
int X(int j){
return s[j] +L;
}
int Y(int j){
return f[j] + (s[j] + L) * (s[j] + L);
}
long double slope(int i, int j){
return (long double)(Y(i) - Y(j)) / (long double)(X(i) - X(j));
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> L;
++L;
F(i, 1, n) cin >> s[i], s[i] += s[i - 1] + 1;
q[++t] = 0;
F(i, 1, n){
while(h < t && slope(q[h], q[h + 1]) < 2 * s[i]) ++ h;
int j = q[h];
f[i] = f[j] + (s[i] - s[j] - L) * (s[i] - s[j] - L);
while(h < t && slope(q[t - 1], q[t]) > slope(q[t - 1], i)) -- t;
q[++ t] = i;
}
cout << f[n] << '\n';
return 0;
}

反思:移项的依据

为了用 \(Function(i)\) 表示出 \(Function(j)\),我们把含 \(i\) 的东西移到等式左边,把含 \(j\) 的东西移到等式右边。以此整理出 "不变的 \(k\),待求解的 \(b\),确定的 \(x, y\)"。 记得 \(f[i]\) 一定要放在截距 \(b\) 里面!因为我们是对 截距 求解极值。

注意 \(k, x, y\) 都是确定的,只有 \(b\) 是待定的。

参考博客:

【学习笔记】动态规划—斜率优化DP(超详细) - 辰星凌 - 博客园 (cnblogs.com)

斜率优化初探:以 [HNOI2008]玩具装箱 为例的更多相关文章

  1. 【斜率优化】BZOJ1010 [HNOI2008]玩具装箱toy

    [题目大意] P教授有编号为1...N的N件玩具,第i件玩具长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.如果将第i件玩具到第j个玩具放到一 个容器中,那么容器的长度将为 x ...

  2. BZOJ 1010: [HNOI2008]玩具装箱toy [DP 斜率优化]

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9812  Solved: 3978[Submit][St ...

  3. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

  4. 【BZOJ 1010】 [HNOI2008]玩具装箱toy (斜率优化)

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9330  Solved: 3739 Descriptio ...

  5. bzoj 1010 [HNOI2008]玩具装箱toy(DP的斜率优化)

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7874  Solved: 3047[Submit][St ...

  6. bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 11893  Solved: 5061[Submit][S ...

  7. [HNOI2008]玩具装箱TOY --- DP + 斜率优化 / 决策单调性

    [HNOI2008]玩具装箱TOY 题目描述: P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京. 他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器 ...

  8. BZOJ 1010: [HNOI2008]玩具装箱toy(DP+斜率优化)

    [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊 ...

  9. bzoj1010: [HNOI2008]玩具装箱toy(DP+斜率优化)

    1010: [HNOI2008]玩具装箱toy 题目:传送门 题解: 很明显的一题动态规划... f[i]表示1~i的最小花费 那么方程也是显而易见的:f[i]=min(f[j]+(sum[i]-su ...

  10. Bzoj 1010: [HNOI2008]玩具装箱toy(斜率优化)

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MB Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定 ...

随机推荐

  1. Java 大文件IO操作效率对比【我说说 你瞅瞅】

    Java 文件IO操作效率对比 注:本文只做时间消耗层面对比,内存占用层面需要特别关注! 1. 参数说明 文件总大小:2,111,993,850 字节(2.11 GB) static String d ...

  2. 【主席树】P3834 【模板】可持久化线段树 2

    P3834 [模板]可持久化线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include <bits/stdc++.h> using namespace ...

  3. SMU Spring 2023 Contest Round 3(2023年湘潭大学新生赛)

    Problem A. 签到啦 从大到小排序,累加大于行李w时输出下标即可 int ans; void solve() { cin >> n >> m; int ans = 0; ...

  4. 面试官:JDK中都用了哪些设计模式?

    设计模式是前辈们经过实践验证总结的解决方案,帮助我们构建出更具可维护性.可扩展性和可读性的代码.当然,在面试的过程中,也会或多或少的被问到.那么今天,我们就来看一道设计模式中的常见面试问题:JDK 中 ...

  5. 推荐5款免费、开箱即用的Vue后台管理系统模板

    前言 在现今的软件开发领域,Vue凭借其高效.灵活和易于上手的特性,成为了前端开发的热门选择.对于需要快速搭建企业级后台管理系统的开发者而言,使用现成的Vue后台管理系统模板无疑是一个明智之举.本文大 ...

  6. 卷积神经网络CNN实战:MINST手写数字识别——数据集下载与网络训练

    数据集下载 这一部分比较简单,就不过多赘述了,把代码粘贴到自己的项目文件里,运行一下就可以下载了. from torchvision import datasets, transforms # 定义数 ...

  7. DDD建模后写代码的正确姿势(Java、dotnet双平台)

    本文书接上回<一种很变态但有效的DDD建模沟通方式>,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新: DDD框架源码(.NET.Java双平台): 加群畅聊,建模分析.技术交流: ...

  8. C#应用 - 破解注入外挂必备神器Harmony

    目录 前言 1,快速开始 1.1 SomeGameClass类 1.2 Patch01类 1.3 MyPatcher类 1.4 跑起来 2,破解 2.1 类库项目 2.2 winform项目 3,注入 ...

  9. css flex属性

    css学的不咋熟,搞一个复杂一点的水平居中,用display 属性 + position属性 + float属性,搞了好久居然没搞出来,然后我去翻资料,发现我最不常用的flex能解决这个问题,于是我就 ...

  10. That's not my Neighbor 之 Chester 问题答案

    Q: What is the meaning of life, the universe and everything else? A: 42 参见:生命.宇宙以及任何事情的终极答案 Q: What ...