题解:洛谷 P1901 发射站
【题目来源】
【题目描述】
某地有 \(N\) 个能量发射站排成一行,每个发射站 \(i\) 都有不相同的高度 \(H_i\),并能向两边(两端的发射站只能向一边)同时发射能量值为 \(V_i\) 的能量,发出的能量只被两边最近的且比它高的发射站接收。显然,每个发射站发来的能量有可能被 \(0\) 或 \(1\) 或 \(2\) 个其他发射站所接受。
请计算出接收最多能量的发射站接收的能量是多少。
【输入】
第 \(1\) 行一个整数 \(N\)。
第 \(2\) 到 \(N+1\) 行,第 \(i+1\) 行有两个整数 \(H_i\) 和 \(V_i\),表示第 \(i\) 个发射站的高度和发射的能量值。
【输出】
输出仅一行,表示接收最多能量的发射站接收到的能量值。答案不超过 \(32\) 位带符号整数的表示范围。
【输入样例】
3
4 2
3 5
6 10
【输出样例】
7
【算法标签】
《洛谷 P1901 发射站》 #栈# #单调栈# #NOI导刊#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int n, h[N], v[N]; // n: 数量,h[i]: 第i个塔的高度,v[i]: 第i个塔的能量
int sum[N]; // sum[i]: 第i个塔最终获得的总能量
int q[N]; // 单调栈,存储塔的编号
int main()
{
cin >> n; // 读入塔的数量
for (int i = 1; i <= n; i++)
{
cin >> h[i] >> v[i]; // 读入每个塔的高度和能量
}
int top = 0; // 栈顶指针
for (int i = 1; i <= n; i++) // 从左到右处理每个塔
{
// 维护单调递减栈:当栈顶塔比当前塔矮时
while (top && h[q[top]] < h[i])
{
// 栈顶塔的能量会流向当前塔i
sum[i] += v[q[top--]]; // 栈顶的能量给i,然后弹出
}
// 如果栈不为空,说明当前塔i的能量会流向栈顶塔
if (top)
{
sum[q[top]] += v[i]; // i的能量给栈顶塔
}
q[++top] = i; // 当前塔i入栈
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans = max(ans, sum[i]); // 找出获得能量最多的塔
}
cout << ans; // 输出最大能量
return 0;
}
// 使用acwing模板二刷
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int n, h[N], v[N], sum[N], stk[N], tt; // n: 塔的数量,h: 塔的高度,v: 塔的能量,sum: 塔接收的总能量,stk: 单调栈,tt: 栈顶指针
int main()
{
cin >> n; // 读入塔的数量
for (int i = 1; i <= n; i++)
{
cin >> h[i] >> v[i]; // 读入每个塔的高度和能量
}
for (int i = 1; i <= n; i++) // 从左到右遍历每个塔
{
// 维护单调递减栈:当栈顶塔比当前塔i矮时
while (tt && h[stk[tt]] < h[i])
{
// 栈顶塔的能量会流向当前塔i
sum[i] += v[stk[tt]]; // 栈顶塔的能量累加到塔i
tt--; // 弹出栈顶
}
// 如果栈不为空,当前塔i的能量会流向栈顶塔
sum[stk[tt]] += v[i]; // 塔i的能量累加到栈顶塔
stk[++tt] = i; // 当前塔i入栈
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans = max(ans, sum[i]); // 找出获得最大能量的塔
}
cout << ans; // 输出最大能量值
return 0;
}
【运行结果】
3
4 2
3 5
6 10
7
浙公网安备 33010602011771号