砖块可以补任意高度差,梯子通吃但数量稀少——把有限的“万能资源”留给最难跨过去的坎,是贪心也是堆的拿手戏。
题目
一条街上有一排建筑,高度依次为
从
共有
输入格式
- 第一行三个整数
; - 第二行
个整数 。
输出格式
- 输出一个整数:最远可到达的建筑编号(从
开始;若连 号都无法离开也输出 )。
样例
样例输入
input
5 5 1
4 2 7 6 9样例输出
output
4样例解释
:高度下降,直接通过; :差 。梯子和砖块都够用,先把差 存入堆(堆大小 ); :高度下降,直接通过; :差 。入堆后堆大小 ,弹出最小的差 ,用 块砖,剩 块砖;- 所有移动都能完成,最远到达
号,输出 。
提示
梯子只有
题解
点击查看题解
核心思路
从左到右扫描每个正高度差
- 把
放入一个小根堆; - 若堆大小超过
,说明有高度差不能都用梯子——弹出堆中最小的差,用砖块支付它( ); - 若某时刻
,说明走到当前这一步的砖块都不够,答案就是当前建筑编号 。
全程砖块非负,则最远能到
为什么正确:砖块只能支付固定的差值,梯子却是“万能”的,所以梯子应该留给最大的
复杂度分析
- 时间复杂度:
- 空间复杂度:
点击查看参考代码
cpp
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
long long b;
int l;
cin >> n >> b >> l;
vector<int> h(n);
for (auto& x : h) cin >> x;
priority_queue<int, vector<int>, greater<int>> pq; // 当前最大的 l 个差中最小者
for (int i = 0; i + 1 < n; ++i) {
int diff = h[i + 1] - h[i];
if (diff <= 0) continue; // 下降无需资源
pq.push(diff);
if ((int)pq.size() > l) { // 梯子不够用砖
b -= pq.top();
pq.pop();
if (b < 0) { // 砖不够 -> 停在 i 号
cout << i << '\n';
return 0;
}
}
}
cout << n - 1 << '\n';
return 0;
}本地运行与提交
powershell
pnpm lab:run -- labs/chapter-05/exercise/E-05-13-furthest-building