算法思路
每个发射站 i 的能量 Vi 只能被最近的、高度比它高的左、右两侧发射站接收。
对任意 i
- 左接收站
L[i]是离i最近的左侧下标满足HL[i] > Hi, - 右接收站
R[i]是离i最近的右侧下标满足HR[i] > Hi。
于是只要把 Vi 加到 L[i] 与 R[i] 的接收总量上,最后统计每个站的接收总量即可。
问题的核心于是转化为“求每个元素左右最近的更大元素”。这是一个经典的 单调递减栈(monotone decreasing stack)可在 O(N) 时间内完成的任务,且在遍历过程中每个元素最多进出栈一次,整体线性。
代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
vector<int> H(N);
vector<int> V(N);
for (int i = 0; i < N; i++) {
cin >> H[i] >> V[i];
}
vector<int> L(N, -1);
vector<int> R(N, -1);
vector<int> stk;
for (int i = 0; i < N; i++) {
while (!stk.empty() && H[stk.back()] <= H[i])
stk.pop_back();
if (!stk.empty())
L[i] = stk.back();
stk.push_back(i);
}
stk.clear();
for (int i = N - 1; i >= 0; i--) {
while (!stk.empty() && H[stk.back()] <= H[i])
stk.pop_back();
if (!stk.empty())
R[i] = stk.back();
stk.push_back(i);
}
vector<ll> E(N, 0LL);
for (int i = 0; i < N; i++) {
if (L[i] >= 0)
E[L[i]] += V[i];
if (R[i] >= 0)
E[R[i]] += V[i];
}
ll max_energy = *max_element(E.begin(), E.end());
cout << max_energy << endl;
}

京公网安备 11010502036488号