首先不难看出一个暴力的 \(dp\) 解法,考虑令 \(dp_{i, j}\) 表示考虑完前 \(i\) 个矩形,第 \(i\) 个矩形左端点在 \(j\) 时所需要的最小花费。

不难有转移:

\[dp_{i, j} = \min\limits_{j - (r_{i - 1} \ - \ l_{i - 1} \ ) \le k \le j + (r_{i} - l_{i})}{dp_{i - 1, k}} + |j - l_i|
\]

继续考虑对上面这个 \(dp\) 进行优化,可以发现的是,这个 \(dp\) 本质上是在对之前的某个区域取 \(\min\) 然后再加上一个之和每个位置有关的绝对值函数。

看起来十分抽象,那么我们可以考虑把抽象问题具体化,将 \(dp_i\) 看作是一个关于 \(j\) 的函数,再来考虑一下转移。

从初始的 \(i = 1\) 开始考虑,不难发现 \(dp_1\) 就是 \(y = |j - l_1|\) 这样一个绝对值函数。

再来考虑 \(i = 2\) 的情况,可以发现前一步取 \(\min\) 本质上是将这个绝对值函数的左段向左平移了 \(r_i - l_i\),右段向右平移了 \(r_{i - 1} - l_{i - 1}\),中间用一段斜率为 \(0\) 的线段接起来。

再来考虑加入 \(|j - l_i|\) 这个绝对值函数,不难发现图像的变化需要分三种情况,但整体的变化方式都是确定的,即 :

  • \(l_i\) 左边的函数斜率整体 \(-1\) 右边的函数斜率整体 \(+1\),同时斜率变化的点的横坐标不变。

可以发现,这样变化后的图像一定还是一个下凸包。

那么就不难通过归纳证明每次转移的过程都是类似于 \(i = 2\) 的情况的。

同时,因为每一个函数 \(dp_i\) 的斜率最大最小值都不会超过 \(\pm |2i - 1|\),因此我们可以考虑直接维护这些斜率变化的拐点。

为了方便起见,如果在这个拐点斜率变化了 \(k\),我们就直接插 \(k\) 个这个点进去代表斜率变化了 \(k\) 个 \(1\)。

首先,因为左右两个函数的平移是不同的,因此我们要分开维护左右两边的断点。

并且,因为函数只是平移,因此我们只需要记录当前平移了多长的距离即可,下面着重来考虑加入一个绝对值函数的过程。

  • 当插入的绝对值函数零点在图像斜率为 \(0\) 的那段上时。

不难发现左边之前的拐点还是拐点,右边亦然。唯一变化的是左边右都会要在 \(l_i\) 处添加一个拐点。

  • 当插入的绝对值函数零点在图像斜率为 \(0\) 的那段左边时。

不难发现此时左边会在 \(l_i\) 处添加两个拐点,同时失去最靠右的拐点,右边会得到左边失去的哪个拐点。(注意这里的拐点实际上代表着斜率变化为 \(1\),这样就方便地处理掉左边做靠右的直线斜率不为 \(-1\) 的情况了)

因为需要取出最右边的端点,因此我们需要一个大根堆来维护左边的拐点。

  • 当插入的绝对值函数零点在图像斜率为 \(0\) 的那段右边时。

同理于上一种情况,用小根堆维护右边的拐点。

那么最终的答案是什么呢?

不难发现其实是最终 \(dp_n\) 斜率为 \(0\) 的那段函数对应的纵坐标。

但是我们并没有记录每一次的纵坐标,怎么办呢?

你会发现每次斜率为 \(0\) 的直线位置总是会向右或者向左变化,而这两次斜率为 \(0\) 的直线中会存在一个交点。

同时因为对于每一层而言,取斜率为 \(0\) 线段上的点总是最优的。

结合上面那条性质,每次选定一个斜率为 \(0\) 的线段做为这一层的 \(j\) 即可,然后计算答案只要计算往下一层斜率为 \(0\) 交点纵坐标的变化量即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 1e5 + 5;
int n, l, r, nL, nR, TL, TR, len, ans, lastlen;
priority_queue <int> L;
priority_queue <int, vector <int>, greater <int> > R;
int read() {
char c; int x = 0, f = 1;
c = getchar();
while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
signed main() {
n = read(), l = read(), r = read();
L.push(l), R.push(l), lastlen = r - l;
for (int i = 2; i <= n; ++i, lastlen = len) {
l = read(), r = read(), len = r - l, TL += len, TR += lastlen;
nL = L.top() - TL, nR = R.top() + TR;
if(l < nL) ans += nL - l, L.pop(), R.push(nL - TR), L.push(l + TL), L.push(l + TL);
else if(l > nR) ans += l - nR, R.pop(), L.push(nR + TL), R.push(l - TR), R.push(l - TR);
else L.push(l + TL), R.push(l - TR);
}
printf("%lld", ans);
return 0;
}

这种方法被称为 \(\rm set\) 维护函数拐点,经常用与维护一次分段函数的变化问题。

AT2347 [ARC070C] NarrowRectangles的更多相关文章

  1. [atARC070E]NarrowRectangles

    记$len_{i}=r_{i}-l_{i}$,即第$i$个区间的长度 用$f_{i,j}$表示前$i$个区间合法,第$i$个区间位于$[j,j+len_{i}]$的最小代价,暴力dp的时间复杂度为$o ...

  2. AtCoder 杂题训练

    前言: 因为要普及了,今年没一等就可以退役去学文化课了,所以暑假把历年noip普及组都刷了一遍,离noip还有50+天,想弄点强化训练什么的. 想了想,就这些天学文化课之余有空就把AtCoder之前那 ...

  3. AtCoder刷题记录

    构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...

  4. 【AtCoder】ARC070

    ARC070 C - Go Home 题目大意:一只袋鼠第i秒可以向左或向右跳i步或者不跳,问从0跳到x的最小时间 就是1,2,3,4...k总和超过x的最小的k,因为如果超过了x的那部分需要减掉的那 ...

随机推荐

  1. 【机器学习】Pandas库练习-获取yahoo金融苹果公司的股票数据

    # 获取yahoo金融苹果公司的股票数据. # 1.分析拉取的数据,找到收盘数据列的列名. # 2.绘制收盘价格柱状图. # 3.分析拉取的数据涨跌率,股价移动平均和波动率. # 4. 找出开盘价和收 ...

  2. 解决ubuntu突然无法联网问题

    一.问题描述 今天使用笔记本远程办公的时候,突然电脑无法联网了,使用chrome浏览器访问网页出现如下错误 This site can't be reachedwww.baidu.com's serv ...

  3. partial write bypass PIE

    第一篇博客,请允许我水一下.BUUCTF上的一题:linkctf_2018.7_babypie 检查一下保护机制: 1 Arch: amd64-64-little 2 RELRO: Partial R ...

  4. 【HTML响应式项目】成人教育官网前端页面(HTML+CSS+JS实现三端适应)

    这个页面是在校参赛的小组项目,除首页和所有课程页面以外由组内成员编写,发博客纯属记录. 项目源码已上传至码云仓库:https://gitee.com/ynavc/sss 项目演示地址:http://y ...

  5. Java初学者作业——编写JAVA程序,在控制台中输入六位员工的姓名,通过随机点名方式,输出当选组长的员工姓名。

    返回本章节 返回作业目录 需求说明: 编写JAVA程序,在控制台中输入六位员工的姓名,通过随机点名方式,输出当选组长的员工姓名. 实现思路: (1)定义字符串类型的数组names,长度为6,用于存储六 ...

  6. PostgreSQL数据库安装Version10.5

    PostgreSQL数据库安装,基于版本10.5安装, 在Linux系统上使用*.gz二进制压缩包手动安装. 操作系统:Red Hat Enterprise Linux Server release ...

  7. 三角网格上的寻路算法Part.1—Dijkstra算法

    背景 最近在研究中产生了这样的需求:在三角网格(Mesh)表示的地形图上给出两个点,求得这两个点之间的地面距离,这条距离又叫做"测地线距离(Geodesic)".计算三角网格模型表 ...

  8. spring security +MySQL + BCryptPasswordEncoder 单向加密验证 + 权限拦截 --- 心得

    1.前言 前面学习了 security的登录与登出 , 但是用户信息 是 application 配置 或内存直接注入进去的 ,不具有实用性,实际上的使用还需要权限管理,有些 访问接口需要某些权限才可 ...

  9. 第10组 Alpha冲刺 (3/6)

    1.1基本情况 ·队名:今晚不睡觉 ·组长博客:https://www.cnblogs.com/cpandbb/p/13971668.html ·作业博客:https://edu.cnblogs.co ...

  10. 第10组 Alpha冲刺 (5/6)(组长)

    1.1基本情况 ·队名:今晚不睡觉 ·组长博客:https://www.cnblogs.com/cpandbb/p/13996848.html ·作业博客:https://edu.cnblogs.co ...