slope trick

news/2024/10/23 8:13:57/文章来源:https://www.cnblogs.com/hugoi/p/18494278

P4597 序列 sequence

首先考虑 \(dp\)

由于只需将序列改为非严格递增,那么就有一个贪心,即最终答案的数集不会变大。

为什么呢?

这是因为只有序列某一位置严格递减时,才会进行修改。

修改可以将前面的数降到和后面的数一样大,或者将后面的数提到和前面的数一样大。

而这样只会让数集变小或不变。

那么设 \(f[i][j]\) 表示将第 \(i\) 个数变为 \(a[j]\) 并使序列非严格递增的最小代价。

\(f[i][j]=\min(f[i-1][k]+|a_i-a_k|)\)

时间复杂度 \(O(n^2)\)

无法通过此题。

为了方便理解,将 \(dp\) 数组拆为两个来看。

\(f[i][j]\) 表示前 \(i\) 个数,将第 \(i\) 个数改为 \(\le j\) 并使序列非严格递增的最小代价。

\(g[i][j]\) 表示前 \(i\) 个数,将第 \(i\) 个数改为 \(j\) 并使序列非严格递增的最小代价。

\(g[i][j]=f[i-1][j]+|a_i-j|\)

\(f[i][j]=\min_{k\le j}(g[i][k])\)

每次固定 \(i\) ,以 \(j\) 为横坐标,函数值为纵坐标,构建平面直角坐标系。

\(G_i\) 表示当 \(i\) 确定后的 \(g\) 函数图像, \(F_i\) 表示当 \(i\) 确定后的 \(f\) 函数图像。

\(G_1\):

\(F_1\):

\(G_2\) 可由 \(F_1\) 转移而来,即在 \(F_1\) 上加一个绝对值函数。

那么 \(F_2\) 就是

或者 \(G_2\)

那么 \(F_2\) 就是

可以发现,\(F_i\) 是一个斜率递增,公差为 \(1\) ,最后一段与 \(x\) 轴平行的凸函数,\(G_2\) 是一个斜率单调递增,最后一段斜率为 \(1\) 的凸函数。

而答案就是 \(G_n/F_n\) 最低点距离 \(x\) 轴的距离。

那么如何维护这两个下凸函数呢?

首先考虑计算答案时需要什么。

可以发现只有 \(a_i\) 比当前决策点小时答案会更新。

从绝对值函数的转折点开始考虑。

转折点处的函数值一定不变,因为转折点的纵坐标为 \(0\)

转折点前的所有函数斜率 \(-1\) ,但决策点横坐标不变。

转折点后的所有函数斜率 \(+1\) ,决策点横坐标同样不变。

原函数为 \(BAGF\),加上了函数 \(JCK\),变成了函数 \(BMNO\)

那么对答案的贡献即为 \(M\)\(G\) 的纵坐标之差。

而纵坐标之差可以分为 \(MA\)\(NG-MA\) 来求。

由于 \(BM\)\(BA\) 的斜率差为 \(1\) ,所以横坐标之差等于纵坐标之差。

由于 \(MN\)\(AG\) 的斜率差为 \(1\) ,所以横坐标之差等于将 \(MN\) 向下平移到 \(A\) 时的 \(NG\) 长度。

这样全部加起来,答案就是新决策点与原决策点的纵坐标之差。

所以我们需要知道所有的 \(\leq0\) 的斜率来维护每次决策点的更新,并计算答案。

如何维护?

首先看 \(a_i\) 在原决策点右侧或原决策点位置的情况。

那就是左侧所有函数的斜率 \(-1\) ,右侧最终取完 \(\min\) 后斜率还是 \(0\)

所以可以想到维护一个优先队列,每次插入 \(a_i\) 表示有一条与 \(x\) 轴平行的横坐标从 \(a_i\)\(+\infty\) 的射线。

那么优先队列中的斜率是什么呢?

可以发现,此时优先队列中点的斜率就是其在优先队列中排名 \(-1\) 的相反数。

但是,如果相邻两个点间的斜率差 \(>1\) ,怎么表示?

那就插入一个点多次。

现在,优先队列中的斜率就变成了与当前点数值相等的最左侧的点在优先队列中的排名-1的相反数

如果 \(a_i\) 在原决策点左侧,又该如何维护优先队列呢?

对原函数的改动还是将 \(a_i\) 左侧的函数斜率 \(+1\),右侧的函数斜率 \(-1\)

相当于在 \(a_i\) 位置插入两个线段,因为当前位置斜率改变了 \(2\)

就完了。

P4331

严格递增,并要求输出方案。

对于严格递增,只需要先将 \(a_i-i\) ,最后再加回去即可转化为非严格递增。

如何输出方案?

先给出结论:每一项先取 \(q.top\) ,最后做一遍后缀 \(\min\) 即可。

首先对于最后一项,取 \(q.top\) 一定存在一种最优方案。

对于前一项,如果比后一项大,不妨将其变的和后一项一样大,这样是保证最优的。

因为每个点取的都是 \(q.top\) ,而这是每个点最小的最优可能值。

如果比后一项小,那么对于这一项到第一项,以当前项的 \(q.top\) 为结尾一定是最优的。

所以每次记录下来 \(q.top\) ,最后做一遍后缀 \(\min\)即可。

练习题

ABC250G

CF865D

ARC070E

P3642 烟火表演

P4272 序列变换

ABC217H

CF1534G

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/819485.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黄绿题选刷

[ABC376D] Cycle找到包含节点 1 的环,直接从节点一出发,BFS,如果第二次遍历到了节点1,直接输出时间即可。点击查看代码 #include <bits/stdc++.h> using namespace std; #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) #define ROF(i, a, b) for (int i …

面试题:如何能够保证T2在T1执行完后执行,T3在T2执行完后执行?——CountDownLatch原理

CountDownLatch的使用方式 CountDownLatch用于某个线程等待其他线程执行完任务再执行,与thread.join()功能类似。常见的应用场景是开启多个线程同时执行某个任务,等到所有任务执行完再执行特定操作,如汇总统计结果。 面试题:如何能够保证T2在T1执行完后执行,T3在T2执行完后…

读数据工程之道:设计和构建健壮的数据系统17存储的原材料

存储的原材料1. 存储 1.1. 存储是数据工程生命周期的基石1.1.1. 是数据获取、转换和服务主要阶段的基础1.1.1.1. 当构建数据管道时,随着数据经过获取、转换和服务阶段,工程师会选择适当的抽象来存储他们的数据1.1.2. 当数据在生命周期中移动时,它会被多次存储1.1.2.1. 必须在…

JAVA 前三次题目集总结

在过去的一个月里完成了java的前三次大作业对于JAVA的语法以及面向对象编程还不台上手,接下来说前三次大作业。 前三次大作业要是围绕答题判题系统展开的每次作业都在完善这个程序的功能可以说 1.第一次作业判分功能 在第一次作业阶段,核心任务是建立一个能够接收题目信息和答…

数据结构 - 树,三探之代码实现

本文介绍了使用数组和链表两种方式实现二叉树,包括初始化、节点操作(如获取、添加、删除)、以及遍历方法(前序、中序、后序、层次遍历)。测试代码已上传至代码库。书接上回,今天和大家一起动手来自己实现树。相信通过前面的章节学习,大家已经明白树是什么了,今天我们主…

不限次数无广告的短网址生成工具推荐

无论是在社交媒体、营销推广还是日常分享,短网址都能让我们更加便捷地分享内容。然而,在众多的短网址生成工具中,用户常常会遇到一些令人头疼的问题:跳转次数限制、插入广告等等。本文将为大家推荐一款不限次数且无广告的短网址生成工具——小码短链接,并详细介绍其优势。…

使用文件重定向

在Linux终端使用了下文件重定向在试的时候命令比较混乱,再重新捋一下:首先使用vim编辑器创建一个名为test.cpp的文件。 具体内容如下:然后使用g++ -o test test.cpp命令编译生成可执行文件test。接着使用vim编辑器创建了输入文件data.txt 具体内容如下:再运行命令./test &l…

The 2022 ICPC Asia Xian Regional Contest 前六题

VP一场,成都赛前找手感,这次还不戳,前三题略讲The 2022 ICPC Asia Xian Regional Contest 签到题题解 CFJ J. Strange Sum 易证最多只能选两个,从大到小排序后 \(\max(0, a_1) + \max(0, a_2)\) 即为所求。 void solve(){cin>>n;vector<ll>a(n+1);for(int i=1;…

利用数组处理批量数据

数组是一组有序数据的集合。数组中各数据的排列有一定规律,下标代表数据在数组中的序号 用一个数组名和下标来唯一的确定数组中的元素 数组中的每一个元素都属于同一个数据类型。不能把不同类型的数据放在同一个数组中 将数组和循环结合起来,可以有效的处理大批量的数据 怎样…

执行yum install 的时候提示【没有可用的软件包】的解决方案

这种情况,可能是yum 源不正确的问题,解决方案如下: 1.执行cd /etc/yum.repos.d,进入这个目录下,查看文件是否存在并检查文件内容的正确性 2、CentOS-Base.repo文件可以在网上下载一个,以下是范文# CentOS-Base.repo # # The mirror system uses the connecting IP addres…

MySQL安装-Linux系统

MySQL安装-Linux系统本文在此只介绍一种安装方式,其他安装方法可以查阅其他相关资料。 一、准备工作 1、下载MySQL社区版 官方网站:https://www.mysql.com/ ,找到下载DOWNLOADS,下载操作系统对应的社区版本。本文使用的数据库版本是5.7.41选择对应的MySQL版本和系统以及系统…

newc++file.cpp在哪

本人的newc++file.cpp文件在C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\VC\VCProjectItems可以在这个cpp文件里面自己选择是否写#define _CRT_SECURE_NO_WARNINGS 如果写了,则在visual studio中新建的cpp文件都有这个这个预处理命令主要是为…