P1901 发射站 - 洛谷
题目描述
某地有 N N N 个能量发射站排成一行,每个发射站 i i i 都有不相同的高度 H i H_i Hi,并能向两边(两端的发射站只能向一边)同时发射能量值为 V i V_i Vi 的能量,发出的能量只被两边最近的且比它高的发射站接收。显然,每个发射站发来的能量有可能被 0 0 0 或 1 1 1 或 2 2 2 个其他发射站所接受。
请计算出接收最多能量的发射站接收的能量是多少。
输入格式
第 1 1 1 行一个整数 N N N。
第 2 2 2 到 N + 1 N+1 N+1 行,第 i + 1 i+1 i+1 行有两个整数 H i H_i Hi 和 V i V_i Vi,表示第 i i i 个人发射站的高度和发射的能量值。
输出格式
输出仅一行,表示接收最多能量的发射站接收到的能量值。答案不超过 32 位带符号整数的表示范围。
样例 #1
样例输入 #1
3
4 2
3 5
6 10
样例输出 #1
7
提示
对于 40 % 40\% 40% 的数据, 1 ≤ N ≤ 5000 , 1 ≤ H i ≤ 1 0 5 , 1 ≤ V i ≤ 1 0 4 1\le N\le 5000,1\le H_i\le 10^5,1\le V_i\le 10^4 1≤N≤5000,1≤Hi≤105,1≤Vi≤104。
对于 70 % 70\% 70% 的数据, 1 ≤ N ≤ 1 0 5 , 1 ≤ H i ≤ 2 × 1 0 9 , 1 ≤ V i ≤ 1 0 4 1\le N\le 10^5,1\le H_i\le 2\times 10^9,1\le V_i\le 10^4 1≤N≤105,1≤Hi≤2×109,1≤Vi≤104。
对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 6 , 1 ≤ H i ≤ 2 × 1 0 9 , 1 ≤ V i ≤ 1 0 4 1\le N\le 10^6,1\le H_i\le 2\times 10^9,1\le V_i\le 10^4 1≤N≤106,1≤Hi≤2×109,1≤Vi≤104。
题解
考察单调栈,本题很好地体现了单调栈的性质。
因为对于某一个发射站,其发射的能量只能被高度更高的站中,距离它最近的站吸收,显然这存在着单调栈问题的特征——「截断」
这种「截断」的性质,被我们利用后就成为了单调栈中的「单调性」,在入栈和出栈的维护中体现为「截断」
首先,单调性和高度有关,我们维护栈中发射站高度的单调性。
因为在栈中,发射站A的能量会被离他最近,靠近栈顶方向的发射站B吸收,发射站B之后靠近栈顶方向的发射站就接收不到发射站A的能量贡献了,所以这时发射站A可以移除,因此我们要实现这种特征。
假定要入栈的发射站称作新站。
-
入栈时,如果新站高度大于栈顶(题目保证所有站高度不等),那么栈顶元素对新站之后的所有元素都没有贡献,于是将其出栈,这样将所有高度小于新站的元素出栈。
-
入栈后,如果栈中新站之前(靠栈底方向)还有一个更高的站,那么新站要向“高站”传输能量
还有1个坑点:需要开3个数组,分别记录高度、发射的能量值,吸收的能量值,然后栈中存储能量站的下标。因为出栈后栈发射站之间的位置关系就变了
#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
using LL = long long;
const int N = 1e6 + 1;
int n;
LL h[N], v[N], energy[N];
stack<int> stk;
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> h[i] >> v[i];
for (int i = 1; i <= n; i++) {
while (!stk.empty() && h[stk.top()] < h[i]) {
energy[i] += v[stk.top()];
stk.pop();
}
if (!stk.empty())
energy[stk.top()] += v[i];
stk.emplace(i);
}
cout << *max_element(energy + 1, energy + 1 + n);
return 0;
}