题解:AtCoder AT_awc0083_c Laying Optical Fiber

【题目来源】

AtCoder:C - Laying Optical Fiber

【题目描述】

Takahashi is an engineer at a telecommunications company. He has been assigned a project to lay new fiber optic cables.

There are \(N\) relay stations along a road, and each station is aligned in a straight line. The stations are numbered \(1, 2, \ldots, N\) in order of increasing distance from the starting point of the road, and the \(i\)-th station is located \(X_i\) meters from the starting point (\(X_1 < X_2 < \cdots < X_N\)). Activating each station \(i\) costs \(C_i\) ten-thousand yen.

Takahashi's project has been allocated a budget of \(M\) ten-thousand yen. To lay the fiber optic cable, Takahashi can select one contiguous interval of stations. Specifically, he chooses a pair of integers \((l, r)\) satisfying \(1 \leq l \leq r \leq N\), and activates all stations from the \(l\)-th to the \(r\)-th. The required cost is the total activation cost of all stations in the chosen interval, \(\displaystyle\sum_{i=l}^{r} C_i\) ten-thousand yen, which must not exceed the budget of \(M\) ten-thousand yen. Note that the cost of laying cables between stations can be ignored.

When a valid \((l, r)\) is chosen under this condition, a fiber optic cable of \(X_r - X_l\) meters can be laid (if \(l = r\), the length is \(0\) meters). If there is no interval that fits within the budget, or if Takahashi chooses not to select any interval, nothing is laid, and the cable length is \(0\) meters.

Find the maximum length of fiber optic cable that Takahashi can lay, in meters.

高桥是一家电信公司的工程师。他被分配了一个铺设新光纤电缆的项目。

沿着一条道路有 \(N\) 个中继站,每个站点在一条直线上排列。站点按照距离道路起点的距离递增顺序编号为 \(1, 2, \ldots, N\),第 \(i\) 个站点位于距离起点 \(X_i\) 米处(\(X_1 < X_2 < \cdots < X_N\))。激活每个站点 \(i\) 的成本为 \(C_i\) 万日元。

高桥的项目被分配了 \(M\) 万日元的预算。为了铺设光纤电缆,高桥可以选择一个连续的站点区间。具体来说,他选择一对满足 \(1 \leq l \leq r \leq N\) 的整数 \((l, r)\),并激活从第 \(l\) 个到第 \(r\) 个的所有站点。所需成本是所选区间内所有站点的总激活成本,即 \(\displaystyle\sum_{i=l}^{r} C_i\) 万日元,这个成本不能超过预算 \(M\) 万日元。注意,站点之间铺设电缆的成本可以忽略不计。

当在此条件下选择一个有效的 \((l, r)\) 时,可以铺设长度为 \(X_r - X_l\) 米的光纤电缆(如果 \(l = r\),则长度为 \(0\) 米)。如果没有符合预算的区间,或者高桥选择不选任何区间,则不铺设任何电缆,电缆长度为 \(0\) 米。

求高桥可以铺设的光纤电缆的最大长度,单位为米。

【输入】

\(N\) \(M\)
\(X_1\) \(C_1\)
\(X_2\) \(C_2\)
\(\vdots\)
\(X_N\) \(C_N\)

  • The first line contains an integer \(N\) representing the number of stations and an integer \(M\) representing the budget (in ten-thousand yen), separated by a space.
  • From the 2nd line to the \((N + 1)\)-th line, information about each station is given.
  • The \((1 + i)\)-th line contains an integer \(X_i\) representing the position (in meters) of the \(i\)-th station and an integer \(C_i\) representing the cost (in ten-thousand yen) required to activate that station, separated by a space.
  • The stations are given in ascending order of position, and it is guaranteed that \(X_1 < X_2 < \cdots < X_N\).

【输出】

Print the maximum length of fiber optic cable that Takahashi can lay, in meters, on a single line.

【输入样例】

5 10
1 2
3 3
7 4
12 5
20 6

【输出样例】

6

【核心思想】

  1. 问题分析:给定 \(N\) 个按位置升序排列的中继站,每个站点有位置 \(X_i\) 和激活成本 \(C_i\)。需要选择一个连续区间 \([l, r]\),使得区间内总成本 \(\sum_{i=l}^{r} C_i \leq M\),同时最大化区间两端的位置差 \(X_r - X_l\)。这是一个双指针(滑动窗口)问题,关键在于如何在成本约束下找到最优区间。

  2. 算法选择

    • 双指针(滑动窗口):使用两个指针 \(l\)(左指针)和 \(r\)(右指针)维护一个窗口 \([l, r]\),保证窗口内总成本不超过 \(M\)
    • 单调性利用:由于站点按位置升序排列,\(X_r - X_l\) 随窗口扩大而增大,但成本约束限制了窗口大小
  3. 关键步骤

    • 初始化\(l = 1\)(左指针),\(sum = 0\)(当前窗口总成本),\(maxn = 0\)(最大位置差)
    • 扩展窗口(右指针 \(r\)\(1\)\(N\)):
      • 将第 \(r\) 个站点的成本加入窗口:sum += c[r]
    • 收缩窗口:当 sum > M 时(成本超限)
      • 不断移除左指针站点的成本:sum -= c[l]
      • 左指针右移:l++
    • 更新答案:如果窗口有效(l <= rsum <= M
      • 计算当前位置差:x[r] - x[l]
      • 更新最大位置差:maxn = max(maxn, x[r] - x[l])
    • 输出最大位置差 \(maxn\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N)\),每个站点最多被左右指针各访问一次
    • 空间复杂度:\(O(N)\),存储站点位置和成本
  5. 双指针(滑动窗口)的核心思想

    • 单调性:右指针 \(r\) 只向右移动,左指针 \(l\) 也只向右移动,不会回退
    • 窗口维护:始终保持窗口 \([l, r]\) 内的总成本不超过预算 \(M\)
    • 贪心策略:对于每个右端点 \(r\),找到最远的左端点 \(l\) 使得区间 \([l, r]\) 的成本不超过 \(M\),此时 \(X_r - X_l\) 是以 \(r\) 结尾的最大位置差
    • 线性扫描:利用双指针的单调性,将暴力枚举的 \(O(N^2)\) 优化到 \(O(N)\)
    • 适用于连续子数组满足某约束条件下的最值问题

【算法标签】

双指针

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;  // 定义数组最大长度
int n, m, maxn, sum;  // 物品数量n,重量限制m,最大差值maxn,当前重量和sum
int x[N], c[N];  // 位置数组x,重量数组c
signed main()
{
    cin >> n >> m;  // 输入物品数量和重量限制
    for (int i=1; i<=n; i++)  // 遍历读取所有物品
        cin >> x[i] >> c[i];  // 输入物品位置和重量
    int l = 1;  // 初始化滑动窗口左指针
    for (int r=1; r<=n; r++)  // 滑动窗口右指针遍历
    {
        sum += c[r];  // 将右指针物品加入当前重量
        while (sum>m && l<=r)  // 如果当前总重量超过限制
        {
            sum -= c[l];  // 移除左指针物品
            l++;  // 左指针右移
        }
        if (l<=r && sum<=m)  // 如果窗口有效且重量不超限
        {
            maxn = max(maxn, x[r]-x[l]);  // 更新位置最大差值
        }
    }
    cout << maxn << endl;  // 输出最大差值
    return 0;  // 程序正常结束
}

【运行结果】

5 10
1 2
3 3
7 4
12 5
20 6
6
posted @ 2026-06-14 10:44  团爸讲算法  阅读(8)  评论(0)    收藏  举报