P1901 发射站 - 洛谷

本文介绍了一道洛谷平台上的算法题目——P1901发射站的问题解决方法。该题涉及多个能量发射站,每个站会向两侧发射能量,能量仅被最近且更高的站接收。通过使用单调栈数据结构,文章详细解释了如何高效地计算出接收最多能量的发射站及其接收的能量值。

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 1N5000,1Hi105,1Vi104

对于 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 1N105,1Hi2×109,1Vi104

对于 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 1N106,1Hi2×109,1Vi104

题解

考察单调栈,本题很好地体现了单调栈的性质。

因为对于某一个发射站,其发射的能量只能被高度更高的站中,距离它最近的站吸收,显然这存在着单调栈问题的特征——「截断

这种「截断」的性质,被我们利用后就成为了单调栈中的「单调性」,在入栈和出栈的维护中体现为「截断」

首先,单调性和高度有关,我们维护栈中发射站高度的单调性。

因为在栈中,发射站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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值