我们考虑经典套路,假设前 \(i - 1\) 个数已经被确定。

设 \(f_k(x)\) 表示 \(a_k = x\) 时 \(\sum_{i = k + 1}^n | \ a_i - a_{i - 1} \ |\) 的最小值。

那么,\(a_i = x\) 当且仅当 \(x\) 取最小值且 \(| \ x - a_{i - 1} \ | + f_i(x)\) 为所有可能中的最小值。

我们设集合 \(I_k = \operatorname{argmin}_{x \in [l_k, r_k]} f_k(x)\)。

一个奇妙性质:\(I_k\) 一定是一个区间。

感性理解。容易发现 \(f_k\) 是一个凸函数,所以当取到最小值时,取值定为一个区间。


我们考虑 \(f_k(x)\) 怎么求。

丁真一下。我们可以考虑直接贪心。若 \(a_i = p\),则 \(a_{i + 1}\) 取 \(\operatorname{argmin}_{x \in [l_k, r_k]} | \ x - p \ |\)。然后转移还是比较简单的。

我们设 \(m_k = \min_{x \in [L_k, R_k]}\{f_k(x)\}\):

\[f_k(x) = \begin{cases}
m_{k+1} + l_k - x & (x < l_k)\\
m_{k+1} & (x\in [l_k, r_k])\\
m_{k+1} + x - r_k & (r_k < x)
\end{cases}
\]

以上贪心可以通过大力分讨得证。但是这一眼正确吧。

那么我们观察 \(f_k(x)\) 的转移式,发现最小值是非常能确定的。于是得到下列结论:

  • 如果 \([L_k, R_k] \cap I_{k+1} \neq \emptyset\),则 \(I_k = [L_k, R_k] \cap I_{k+1}\)。
  • 如果 \(R_k < l_{k + 1}\),则 \(I_k = R_k\)。
  • 如果 \(L_k > r_{k + 1}\),则 \(I_k = L_k\)。

综上,我们求出了 \(I\)。\(f\) 实际上不需要求出。


回到原题。我们要找到 \(x\) 使 \(x\) 取最小值且 \(| \ x - a_{i - 1} \ | + f_i(x)\) 为所有可能中的最小值。

仍然是大力分讨:

  • \(a_{i - 1} \in I_i\) 时,\(a_i = a_{i - 1}\)。

  • \(L_i \leq a_{i - 1} < l_i\) 时,\(a_i = a_{i - 1}\)。

  • \(a_{i - 1} < L_i\) 时,\(a_i = l_i\)。

  • \(a_{i - 1} > r_i\) 时,\(a_i = r_i\)。

发现上述过程可以简化为 \(a_i\) 取 \([L_i, r_i]\) 中最靠近 \(a_{i - 1}\) 的值。


以下是代码实现。

#include <bits/stdc++.h>
using namespace std; long long read() {
char c = getchar();
long long x = 0, p = 1;
while ((c < '0' || c > '9') && c != '-') c = getchar();
if (c == '-') p = -1, c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * p;
} const int N = 5e5 + 7; int n;
int l[N], r[N], L[N], R[N];
int ans[N]; void solve() {
n = read();
for (int i = 1; i <= n; i ++)
L[i] = read(), R[i] = read();
l[n] = L[n], r[n] = R[n];
for(int i = n - 1; i >= 1; i --) {
if (R[i] < l[i + 1]) {
l[i] = r[i] = R[i];
} else if (L[i] > r[i + 1]) {
l[i] = r[i] = L[i];
} else {
l[i] = max(L[i], l[i + 1]);
r[i] = min(R[i], r[i + 1]);
}
}
ans[1] = l[1];
for(int i = 2; i <= n; i++) {
if (ans[i - 1] >= l[i] && ans[i - 1] <= r[i])
ans[i] = ans[i - 1];
else if (ans[i - 1] >= L[i] && ans[i - 1] < l[i])
ans[i] = ans[i - 1];
else if (ans[i - 1] < L[i])
ans[i] = L[i];
else ans[i] = r[i];
}
for(int i = 1; i <= n; i ++) cout << ans[i] << ' ';
} signed main() {
int t = 1;
while (t --) solve();
return 0;
}

ARC 175 C 题解的更多相关文章

  1. ARC 122 简要题解

    ARC 122 简要题解 传送门 A - Many Formulae 考虑对于每个数分别算其贡献. 通过枚举该数前面的符号,借助一个非常简单的 \(\mathrm{DP}\)(\(f_{i,0/1}\ ...

  2. HTML5移动开发学习笔记之Canvas基础

    1.第一个Canvas程序 看的是HTML5移动开发即学即用这本书,首先学习Canvas基础,废话不多说,直接看第一个例子. 效果图为: 代码如下: <!DOCTYPE html> < ...

  3. HTML5系列:HTML5绘图

    1. canvas元素基础 canvas元素是HTML5中新增的一个重要元素,专门用来绘制图形. 在页面中使用canvas元素绘制图形需要经过的三个步骤: 步骤一  使用canvas元素创建一个画布区 ...

  4. 2015年---移动端webapp知识总结

    没想到这样又过了5个月了,近期辞职了,所以我有时间来做总结. 这段时间里我学习了很多东西,而且都是我们移动端webapp的同学值得去学习的. 我先告诉大家我这次写的总结,有以下内容: 1.body的背 ...

  5. 用画布canvas画安卓logo

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. window环境下备份与恢复(实际操作)

    C:\Documents and Settings\xuzhengzhu>sqlplus /nolog SQL*Plus: Release 10.2.0.1.0 - Production on ...

  7. 【题解】Atcoder ARC#96 F-Sweet Alchemy

    首先,我们发现每一个节点所选择的次数不好直接算,因为要求一个节点被选择的次数大于等于父亲被选择的次数,且又要小于等于父亲被选择的次数 \(+D\).既然如此,考虑一棵差分的树,规定每一个节点被选择的次 ...

  8. 【题解】Atcoder ARC#94 F-Normalization

    再次膜拜此强题!神级性质之不可能发现系列收藏++:首先,对于长度<=3的情况,我们采取爆搜答案(代码当中是打表).对于长度>=4的情况,则有如下几条玄妙的性质: 首先我们将 a, b, c ...

  9. [题解] Atcoder Regular Contest ARC 148 A B C E 题解

    点我看题 题目质量一言难尽(至少对我来说 所以我不写D的题解了 A - mod M 发现如果把M选成2,就可以把答案压到至多2.所以答案只能是1或2,只要判断答案能不能是1即可.如果答案是1,那么M必 ...

  10. [题解] Atcoder Regular Contest ARC 147 A B C D E 题解

    点我看题 A - Max Mod Min 非常诈骗.一开始以为要观察什么神奇的性质,后来发现直接模拟就行了.可以证明总操作次数是\(O(nlog a_i)\)的.具体就是,每次操作都会有一个数a被b取 ...

随机推荐

  1. 代码重构(OOP)-小栗子(PyQt5)

    主要是为了练习下 面向对象, 不断提醒自己代码一定要写成 营销风格, 和优雅. 最近在B站上看一下关于 Python GUI 编程的内容. 恰好呢, 前不久的一个 将本地 Ecxcel 数据 发布到 ...

  2. TVM:设计与架构

    本文档适用于想要了解 TVM 架构和/或积极开发项目的开发人员.页面组织如下: 示例编译流程概述了 TVM 将模型的高层描述转换为可部署模块所采取的步骤.要开始使用,请先阅读本节. 逻辑架构组件部分描 ...

  3. WPF透明框设置Demo

    <Window x:Class="GuiDB.EBMultiEditTextWin" xmlns="http://schemas.microsoft.com/win ...

  4. linux与docker知识积累

    0.在CentOS中,启动docker : sudo systemctl start docker 1.在 CentOS 中,要删除一个文件夹及其内容,可以使用 rm 命令的 -r 或 --recur ...

  5. C#8.0,9.0,10.0常见新语法学习

    顶级语句 (1)一个项目最多只能有一个文件具有顶级语句,就是直接写代码,如果存在多个,则会报错, (2)如果顶级语句和Main共存,则只调用顶级语句 (3)如果没有顶级语句,则必须有Main 简化us ...

  6. django-channels自定义中间件验证token的方法

    测试版本: python 3.8 djnago 3.2 channels 3.0 需求 在使用channels 建立websocket连接的时候,需要验证客户端的token,并保存一些关键信息 实现原 ...

  7. HarmonyOS运动开发:如何绘制运动速度轨迹

    前言 在户外运动应用中,绘制运动速度轨迹不仅可以直观地展示用户的运动路线,还能通过颜色变化反映速度的变化,帮助用户更好地了解自己的运动状态.然而,如何在鸿蒙系统中实现这一功能呢?本文将结合实际开发经验 ...

  8. 鸿蒙仓颉开发语言实战教程:自定义tabbar

    大家周末好呀,今天继续分享仓颉语言开发商城应用的实战教程,今天要做的是tabbar. 大家都知道ArkTs有Tabs和TabContent容器,能够实现上图的样式,满足基本的使用需求.而仓颉就不同了, ...

  9. Java HashMap和ConcurrentHashMap知识点梳理

    jdk 8 HashMap 扩容之后旧元素存放位置是? java 在扩容的时候会创建一个新的 Node<K,V>[],用于存放扩容之后的值,并将旧的Node数组(其大小记作n)置空:至于旧 ...

  10. ZCPC17th E Easy DP Problem

    ZCPC17th E Easy DP Problem 希望更丰富的阅读体验?来我的网站阅读趴! Problem 由于这题前面的思维推到部分我没有参与,主要是现学(复习)了一下主席树,所以主要讲主席树的 ...