题解:AtCoder AT_awc0089_c A Walk to Cherry Blossom Viewing

【题目来源】

AtCoder:C - A Walk to Cherry Blossom Viewing

【题目描述】

In the town where Takahashi lives, there are \(N\) cherry blossom spots arranged in a straight line, numbered Spot \(1\), Spot \(2\), \(\ldots\), Spot \(N\) in order. Adjacent spots are connected by promenades, and there exists promenade \(i\) (\(1 \leq i \leq N - 1\)) connecting Spot \(i\) and Spot \(i + 1\). There are \(N - 1\) promenades in total.

Each Spot \(j\) (\(1 \leq j \leq N\)) has a score \(P_j\) representing the beauty of the cherry blossoms at that location. Additionally, each promenade \(i\) (\(1 \leq i \leq N - 1\)) has a maintenance cost \(C_i\).

Takahashi plans to maintain a contiguous interval of promenades to create a walking course. Specifically, he chooses integers \(l, r\) (\(1 \leq l \leq r \leq N - 1\)) and maintains all of promenade \(l\), promenade \(l+1\), \(\ldots\), promenade \(r\). By doing so, he can visit all of Spot \(l\), Spot \(l+1\), \(\ldots\), Spot \(r+1\) along the maintained promenades as his walking course.

The satisfaction obtained from the walking course is defined as the sum of the scores of the \(r - l + 2\) spots included in the course:

\(P_l + P_{l+1} + \cdots + P_{r+1}\)

On the other hand, the total cost of maintenance is:

\(C_l + C_{l+1} + \cdots + C_r\)

Takahashi's budget is \(B\), and he can only choose \((l, r)\) such that the total cost is at most \(B\). Takahashi must choose and maintain exactly one such interval.

Among all ways to choose \((l, r)\) such that the total cost is at most \(B\), find the maximum value of the satisfaction.

Note that, due to the constraints, the maintenance cost of each promenade is at most \(B\), so \(l = r\) (maintaining just one promenade) always satisfies the condition, and there exists at least one valid choice of \((l, r)\).

在高桥居住的小镇上,有 \(N\) 个赏樱景点排成一条直线,按顺序编号为景点 \(1\)、景点 \(2\)、……、景点 \(N\)。相邻景点由散步道连接,存在散步道 \(i\)\(1 \leq i \leq N - 1\))连接景点 \(i\) 和景点 \(i + 1\)。总共有 \(N - 1\) 条散步道。

每个景点 \(j\)\(1 \leq j \leq N\))有一个分数 \(P_j\),代表该地点樱花的美观度。此外,每条散步道 \(i\)\(1 \leq i \leq N - 1\))有一个维护成本 \(C_i\)

高桥计划维护一个连续区间的散步道,以创建一条步行路线。具体来说,他选择整数 \(l, r\)\(1 \leq l \leq r \leq N - 1\)),并维护散步道 \(l\)、散步道 \(l+1\)、……、散步道 \(r\)。通过这样做,他可以沿着维护好的散步道访问所有景点 \(l\)、景点 \(l+1\)、……、景点 \(r+1\) 作为他的步行路线。

从步行路线中获得的满意度定义为路线中包含的 \(r - l + 2\) 个景点的分数之和:

\(P_l + P_{l+1} + \cdots + P_{r+1}\)

另一方面,维护的总成本为:

\(C_l + C_{l+1} + \cdots + C_r\)

高桥的预算是 \(B\),他只能选择总成本不超过 \(B\)\((l, r)\)。高桥必须选择并维护恰好这样一个区间。

在所有总成本不超过 \(B\)\((l, r)\) 选择方式中,求满意度的最大值

注意,由于约束条件,每条散步道的维护成本不超过 \(B\),因此 \(l = r\)(只维护一条散步道)总是满足条件,至少存在一个有效的 \((l, r)\) 选择。

【输入】

\(N\) \(B\)
\(P_1\) \(P_2\) \(\ldots\) \(P_N\)
\(C_1\) \(C_2\) \(\ldots\) \(C_{N-1}\)

  • The first line contains an integer \(N\) representing the number of cherry blossom spots and an integer \(B\) representing the budget, separated by a space.
  • The second line contains \(N\) integers \(P_1, P_2, \ldots, P_N\) representing the scores of each spot, separated by spaces.
  • The third line contains \(N - 1\) integers \(C_1, C_2, \ldots, C_{N-1}\) representing the maintenance costs of each promenade, separated by spaces.

【输出】

Print in one line the maximum satisfaction among all maintenance intervals whose total cost is at most \(B\).

【输入样例】

5 10
3 1 4 1 5
2 3 4 5

【输出样例】

10

【核心思想】

  1. 问题分析:给定 \(N\) 个景点的分数 \(P_j\)\(N-1\) 条散步道的维护成本 \(C_i\),选择一段连续的散步道区间 \([l, r]\),使得维护总成本不超过预算 \(B\),同时最大化覆盖的景点分数之和 \(P_l + P_{l+1} + \cdots + P_{r+1}\)。这是一个双指针(滑动窗口)问题,关键在于维护一个满足成本约束的窗口,并动态调整窗口大小。

  2. 算法选择

    • 双指针(滑动窗口):用左右两个指针维护一个满足成本约束的区间
    • 前缀和优化:维护当前窗口内的景点分数之和与散步道成本之和
    • 贪心调整:当成本超过预算时,从左端收缩窗口
  3. 关键步骤

    • 初始化
      • ans = 0:记录最大满意度
      • sumP = p[1]:当前窗口内的景点分数之和
      • sumC = 0:当前窗口内的散步道成本之和
      • l = 1:左指针
    • 右指针扩展(遍历 \(r\)\(1\)\(n-1\)):
      • sumP += p[r+1]:将新景点加入窗口
      • sumC += c[r]:加上新散步道的成本
    • 左指针收缩(当 sumC > b 时):
      • sumC -= c[l]:移除左端散步道的成本
      • sumP -= p[l]:移除左端景点的分数
      • l++:左指针右移
    • 更新答案ans = max(ans, sumP)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N)\),每个元素最多被左右指针各访问一次
    • 空间复杂度:\(O(N)\),存储景点分数和散步道成本数组
  5. 双指针的核心思想

    • 窗口维护:用左右指针维护一个满足约束条件的连续区间
    • 单调性:右指针只向右移动,左指针根据条件调整
    • 贪心策略:当窗口不满足条件时,从左端收缩,保证窗口内始终满足约束
    • 最优性:每个位置作为右端点时,都找到了满足条件的最左端点
    • 适用于子数组/子区间最值、约束条件下的区间选择类问题

【算法标签】

双指针

【代码详解】

#include <bits/stdc++.h>
using namespace std;

// 定义长整型别名,便于处理大数据
#define int long long

// 定义数组最大容量
const int N = 500005;

// 全局变量声明
int n;              // 节点数量
int b;              // 预算上限(可承受的最大连接成本)
int p[N];           // 每个节点的价值
int c[N];           // 相邻节点之间的连接成本

// 主函数入口(使用signed避免与long long冲突)
signed main()
{
    // 读取节点数量和预算上限
    cin >> n >> b;

    // 读取每个节点的价值
    for (int i = 1; i <= n; i++)
        cin >> p[i];

    // 读取相邻节点之间的连接成本(共n-1条边)
    for (int i = 1; i < n; i++)
        cin >> c[i];

    // 滑动窗口:寻找在预算范围内能获得的最大总价值
    int ans = 0;            // 记录最大总价值
    int sumP = p[1];        // 当前窗口内的总价值
    int sumC = 0;           // 当前窗口内的总连接成本

    // 右指针从1到n-1移动,不断尝试扩大窗口
    for (int r = 1, l = 1; r < n; r++)
    {
        sumP += p[r + 1];   // 将新节点加入窗口
        sumC += c[r];       // 加上新连接的成本

        // 如果总成本超过预算,从左端收缩窗口
        while (l <= r && sumC > b)
        {
            sumC -= c[l];   // 移除左端的连接成本
            sumP -= p[l];   // 移除左端节点的价值
            l++;            // 左指针右移
        }

        // 更新最大总价值
        ans = max(ans, sumP);
    }

    // 输出结果
    cout << ans << endl;

    return 0;
}

【运行结果】

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