UTS Open '21 P6 - Terra Mater
前言
本题是一道很好的“dp”题,无论是正难反易,还是模型转化都值得称赞,尤其是最后的神之一手,让我大脑宕机。
题意描述
给定一个长度为 \(N\) 的序列 \(H\),修改不超过 \(K\) 个数,使得 \(\max_{1}^{N - 1}{H_{i + 1} - H_i}\) 最小。
\(2 \le N \le 2 \times 10^5\) ,\(0 \le K \le N\) ,\(1 \le H_i \le 10^9\)
思路推导 & 做法
首先,对于这一类最大值最小的问题,我们有一个模板化的思考方向——二分答案,在尝试后,发现对于该题在确定答案后再判断是否有解是有用的,因为答案限制了相邻 \(H_i\) 的取值,同时并没有什么可贪心或能转化为图论的地方,所以考虑 \(\text{dp}\) check。
然后怎么做呢?在思考良久后,发现这道题很难(这不废话吗),连暴力 \(\text{dp}\) 都打不出来。直接硬做做不出来,就要思考如何把题目进行转化以降低难度。此时就要发挥你惊人的注意力,像瞪几何大题一样敏锐地发现直接做做不出来的原因在于若该修改 \(i\) 你在 \(i + 1\) 就不知道上一个选了什么数也无法定义进状态里,所以就要把从某个地方转移过来的数固定下来,所以就要将“不修改”放进 \(\text{dp}\) ,也就是正难反易,于是定义 \(dp_i\) 表示考虑完前 \(i\) 座山丘,第 \(i\) 座山丘不修改,最多能有多少座山丘不修改。
考虑状态转移,设二分的答案为 \(danger\),若 \(2\) 座山丘 \(i, j (j < i)\) 都不修改,则要满足对于山丘 \(k \in (j, i)\) 都修改的情况下,也就是最容易满足的情况下能满足条件,即 \(|H_i - H_j| \le danger \times (i - j)\) 。所以有如下 \(\text{dp}\) 转移式:
\]
目前我们有了 \(O(N^2 \log {10^9})\) 的做法,但这明显不够,所以我们要把 \(\text{dp}\) 优化进 \(O(N \log N)\) 及以内。
现在我们要从状态转移方程入手,发现其中最不规整也最难优化的是 \(|H_i - H_j| \le danger \times (i - j)\) 这一个条件,绝对值的存在让我们不能轻易优化,所以要拆绝对值,条件就变成了
\]
再将具有同一变量的值移到同侧,变为
\]
发现所有与 \(j\) 有关的和与 \(i\) 有关的都分列两侧,所以可以另定义权值,把条件变漂亮。定义 \(X_i = danger * i\) ,定义 \(v_i \ge v_j\) 为 \(X_i - H_i \ge X_j - H_j 且 X_i + H_i \ge X_j + H_j\) (这式子好整齐啊,要不是我推出来的一定还有转化),反之为 \(\le\) ,问题就转化为给定长度为 \(n\) 的序列 \(v\) ,求该序列的最长不下降子序列 。
当你做到这一步时大抵是会欣喜若狂像我一样 ,以为马上就切掉这道题了,但好题就是好题,总在你得意忘形时给你沉重一击(笑容凝固)。你惊世骇俗地发现加上 \(i\) 这一维下标后就变成了三维偏序,解决的经典办法是CDQ分治或二维树状数组,但 \(O(N \log^2 N)\),总时间 \(O(N \log^2 N log 10^9)\) ,然后你的动作be like:Win + R ——calc——\(200000 \times (\frac{log_{10}^{200000}}{log_{10}^{2}})^2 \times \frac{log_{10}^{10^9}}{log_{10}^{2}} = 1854230461.3827186693864795412925\dots\) ,随即亲切地问候了出题者的祖宗苦思冥想,始终不得其解。
神之一手
我翻开算法圣经(蓝本)一查,这三维偏序没有界限,歪歪斜斜的每页上都写着CDQ分治几个字。我横竖想不通,仔细看了半日,才从字缝里看出来,满本都写着两个字是 \(O(N \log^2 N)\)!
当你接近崩溃的时候,你忽地想起了推出的式子和心中的想法,抱着试一试的心态去推了一下式子进行转化(回收伏笔),脑袋里还想着什么高深算法,把三减个一变成二,突然发现答案就在笔下。
若 \(v_j \ge v_i (j < i)\) ,则
\]
\]
变形得
\]
\]
将 \(X_i,X_j\) 还原回去
\]
\]
\]
所以我们可以得出若 \(j < i\) ,\(v_j \le v_i\) ,所以当交换 \(v_j, v_i\) 后(权值不变),\(dp_i\) 一定不对 \(dp_j\) 产生贡献,所以交换两个数后答案一定不会变大。
若 \(v_i \ge v_j (j < i)\) ,则
\]
\]
由此得出如果按某一维排序后 \(dp_j\) 仍然在 \(dp_i\) 前且一定满足 \(v_i \ge v_j\) ,\(dp_i\) 仍然可以从 \(dp_j\) 转移,所以原本可转移的方向现在仍然存在,故排序后答案不会变小。
交换 \(v_i, v_j\) 后答案不变大又可以缩小范围为对 \(v\) 排序后答案不变大,此时答案也不变小,所以任意按某一维排序后答案不变!!!
这神之一手直接把索引 \(i\) 的一维砍掉,成功把三维偏序转化为二维偏序,直接用 \(\text{LIS}\) 模板树状数组即可。
solution
思路想通后代码异常简单。
/*
address:https://dmoj.ca/problem/utso21p6
AC 2025/1/11 16:49
*/
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x & -x)
const int N = 2e5 + 5;
int n, k;
int h[N];
struct BinaryTree {
int c[N];
inline void init(int n) { fill(c + 1, c + n + 1, 0); }
inline void change(int x, int k) { for (;x <= n;x += lowbit(x)) c[x] = max(c[x], k); }
inline int query(int x) {
int ret = 0;
for (;x > 0;x -= lowbit(x)) ret = max(ret, c[x]);
return ret;
}
}BIT;
typedef long long LL;
pair<LL, LL>a[N];
LL disc[N];
int dp[N];
inline bool check(int danger) {
BIT.init(n + 1);
for (int i = 1;i <= n;i++) a[i] = { 1ll * danger * i - h[i],1ll * danger * i + h[i] };
sort(a + 1, a + n + 1);
for (int i = 1;i <= n;i++) disc[i] = a[i].second;
sort(disc + 1, disc + n + 1);
int m = unique(disc + 1, disc + n + 1) - disc - 1;
for (int i = 1;i <= n;i++) a[i].second = lower_bound(disc + 1, disc + m + 1, a[i].second) - disc;
for (int i = 1;i <= n;i++) {
dp[i] = BIT.query(a[i].second) + 1;
BIT.change(a[i].second, dp[i]);
}
for (int i = 1;i <= n;i++)
if (dp[i] >= n - k) return true;
return false;
}
int main() {
int T;scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k);
for (int i = 1;i <= n;i++) scanf("%d", &h[i]);
int l = 0, r = 1e9, ans = 1e9;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%d\n", ans);
}
return 0;
}
总结
这道题单说前几步难度就已经很大了,最后出题者的阴险巧妙构思画龙点睛,让这道题的难度更上一层。这种巧妙的题还是少见,值得珍惜。
同时也明白了莫要
只言片语尽显高见, 行动却似矮人观场
UTS Open '21 P6 - Terra Mater的更多相关文章
- P6 EPPM 安装与配置指南 16 R1 2016.4
关于安装和 配置P6 EPPM 本指南告诉你如何自动 安装和配置您的应用程序. 在您开始之前,阅读 先决条件 P6 EPPM配置 (7页). 安装P6 EPPM 您将使用 安装程序 (窗口) . ...
- P6 EPPM手动安装指南(Oracle数据库)(一)
P6 EPPM手动安装指南(Oracle数据库) P6 EPPM Manual Installation Guide (Oracle Database) 1. 内容... 1 1.1. ...
- P6 EPPM Manual Installation Guide (Oracle Database)
P6 EPPM Manual Installation Guide (Oracle Database) P6 EPPM Manual Installation Guide (Oracle Databa ...
- P6 EPPM Installation and Configuration Guide 16 R1 April 2016
P6 EPPM Installation and Configuration Guide 16 R1 April 2016 Contents About Installing and ...
- P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1
P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1 May ...
- 面试阿里前端P6血和泪换来的收获
我的一个朋友在前端耕耘一段时间,也在网上进行了高度培训学习,最近一段时间他打算跳槽去阿里面试前端P6开发岗位,结果被痛虐了一回,估计从此以后会给他留下不可磨灭的阴影啊 真是十年生死两茫茫,一鲁代码 ...
- Linux ns 4. UTS Namespace 详解
目录 1. 使用简介 1.1 hostname 1.2 domainname 1.3 uname 2. 代码分析 2.1 copy_utsname() 2.2 sethostname() 2.3 ge ...
- 【夯实Mysql基础】MySQL性能优化的21个最佳实践 和 mysql使用索引
本文地址 分享提纲: 1.为查询缓存优化你的查询 2. EXPLAIN 你的 SELECT 查询 3. 当只要一行数据时使用 LIMIT 1 4. 为搜索字段建索引 5. 在Join表的时候使用相当类 ...
- 2-1 Linux 操作系统及常用命令
根据马哥linux初级视频 2-1.2-2来编辑 1. GUI与CLI GUI: Graphic User Interface CLI: Command Line Interface 注:在Windo ...
- Fedora 21 安装 Nvidia 驱动以及失败后的补救方法
在 Linux 桌面系统下玩了这么久,大部分时间都是使用 Ubuntu,偶尔使用一下 Fedora.我的电脑中安装有多个 Linux 发行版,见这里<在同一个硬盘上安装多个Linux发行版及Fe ...
随机推荐
- 【一步步开发AI运动小程序】十四、主包超出2M大小限制,如何将插件分包发布?
随着人工智能技术的不断发展,阿里体育等IT大厂,推出的"乐动力"."天天跳绳"AI运动APP,让云上运动会.线上运动会.健身打卡.AI体育指导等概念空前火热.那 ...
- MySQL 主从复制之多线程复制
目录 一.MySQL 多线程复制的背景 二.MySQL 5.5 主从复制 1.原理 2.部署主从复制 2.1.主节点安装配置MySQL 5.5 2.2.从节点安装配置MySQL 5.5 3.检查主从库 ...
- go get 和 go install 对比
(一)命令定义和区别 go install 和 go get 都是 Go 语言的工具命令,但它们之间有一些区别. go get:用于从远程代码存储库(如 GitHub)中下载或更新 Go 代码包.它会 ...
- 轻量数据库管理工具之adminer
github: https://github.com/vrana/adminer 官方文档:https://www.adminer.org/#download Supports: MySQL, Mar ...
- git 推送代码到多个 远端仓库
业务场景 在开发代码时,有时希望将代码推送到两个远端仓库. 实现方法 git remote add origin giturl1 git remote add backup giturl2 git p ...
- Java日志记录几种实现方案
在平时使用到一些软件中,比如某宝或者某书,通过记录用户的行为来构建和分析用户的行为数据,同时也能更好优化产品设计和提升用户体验.比如在一个订单系统中,需要确定追踪用户的行为,比如: 登录/登出 浏览商 ...
- RepoDB:一个介于Dapper、EFCore之间.Net的ORM库
推荐一个介轻量ORM和全功能ORM的开源项目. 01 项目简介 RepoDB 提供了基本操作所需的方法,同时也提供了一些高级功能,如第二层缓存.跟踪.仓储.属性处理器和批量/大量操作.支持的数据库,包 ...
- [OS] 计算机资源虚拟化技术
1 定义:计算机资源虚拟化 服务器虚拟化主要通过软件技术将物理服务器的硬件资源抽象化,创建多个独立的虚拟服务器环境. 2 虚拟化技术方向 以下是一些常见的服务器虚拟化方式和工具: 基于hypervis ...
- R数据分析:做量性研究的必备“家伙什”-furniture包介绍
In conjunction with many other tidy tools, the package should be useful for health, behavioral, and ...
- PG 实现 Dynamic SQL
CREATE OR REPLACE FUNCTION public.exec( text) RETURNS SETOF RECORD LANGUAGE 'plpgsql' AS $BODY$ BEGI ...