铺设道路

GitHub跳转原题关系图返回列表

把每天的区间填平操作看成给相邻深度差分,答案为相邻深度差的正部之和 max(d_i - d_{i-1}, 0)。

OJ: roj

题目 ID: 3658

难度:普及

标签:贪心差分

创建: 2026-10-02 13:43

更新: 2026-10-06 16:14

题目描述

道路长度为 nn,第 ii 段下陷深度为 did_i。每次操作选一段区间 [L,R][L,R](操作前区间内深度均大于 00),把 dL,…,dRd_L,\dots,d_R 同时减 11,求把整条路填平所需的最少操作次数。输入:第一行 nn,第二行 d1,…,dnd_1,\dots,d_n;输出:最少操作次数。样例输入:n=6,d=[4,3,2,5,3,5];样例输出:9。数据范围:1≤n≤1051 \le n \le 10^5,0≤di≤1040 \le d_i \le 10^4。

思路

把每次操作看成砖块图(位置为列、高度为 did_i)里的一条横条:只有比左邻高出来的层,左邻没有砖可铺,必须以该位置为左端点新开一次操作,因此答案是相邻深度差的正部之和 ∑i=1nmax⁡(di−di−1,0)\sum_{i=1}^{n} \max(d_i - d_{i-1}, 0)(约定 d0=0d_0 = 0)。一次线性扫描即可,样例即 4+3+2=94+3+2=9。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 13:43
# update_at: 2026-10-02 13:43

import sys
from itertools import pairwise


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    n = next(data)
    depth = [next(data) for _ in range(n)]

    # 每天只能在"深度非零"的连续段内整体 -1,把每个位置填到 0 的次数里
    # 与左邻共用的部分不会重复计数;答案 = 相邻差分的正部之和。
    ans = sum(max(cur - prev, 0) for prev, cur in pairwise([0] + depth))

    print(ans)


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-06 16:14
 * update_at: 2026-10-06 16:14
 */

#include <cstdio>

typedef long long ll;

const int MAXN = 1e5 + 5;

int n;
ll d[MAXN]; // d[i] 表示第 i 天的道路深度

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%lld", &d[i]);

    // 每次操作填平一个区间,把"竖直视角"看成铺横条:
    // 只有比左邻高出来的层必须以 i 为左端点新开一次操作,
    // 答案 = sum(max(d[i] - d[i-1], 0)),约定 d[0] = 0。
    ll ans = 0;
    for (int i = 1; i <= n; ++i)
        if (d[i] > d[i - 1])
            ans += d[i] - d[i - 1];

    printf("%lld\n", ans);
    return 0;
}