P1901 发射站

题目传送门

一、解题思路

1、又能向左发射,又能向右发射,不太好想。复杂问题都是由简单问题组装而来,我们先来考虑这个问题的一半。假如每个发射站只会向左发射信号,如果第i个发射塔比它左边的发射站都高,那么第i个发射站左边的站点就不可能收到i站点及i站后面所有站点发送来的信号,因为就算有,也被i拦截了。再保留这样的站点也就没有意义了,干掉就完了。

其实,本质上是在维护一个栈顶向栈底递增的单调栈,每次一个元素入栈之后,设此时栈顶为tt,那么该元素发射的信号只能被位于tt1的站点收到,这样就起到了提速的作用。

2、向左发射信号的过程做完后再做一遍向右发射信号的过程。

3、找出哪个站点收到的信号最多。

二、数组模拟栈法

#include <bits/stdc++.h>

using namespace std;
const int N = 1000010;
int n;
int a[N], b[N]; //高度与能力值
int s[N];//结果数组
int ans; //最大值

//用数组模拟栈,每一个栈内的元素,都是需要找到“比自己高度小的,离自己最近”的发射塔,才能享受它带来的能量值。
int stk[N]; //内容:序号
int tt;     //指针,默认是0

void add(int i) {
    //把栈顶高度比自己小的出栈,这样的是不能享受i个发射塔带来的能量滴~
    while (tt && a[i] > a[stk[tt]]) tt--;
    //如果找着了一个高度比自己大的发射塔,那么,这个位置的发射塔将享受i个发射塔带来的能量。
    s[stk[tt]] += b[i];
    //把自己入栈,等待其它人给自己带来能量,enjoy!
    stk[++tt] = i;
}

int main() {
    //输入
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i] >> b[i];

    //从左向右扫一遍
    for (int i = 1; i <= n; i++) add(i);

    //还原指针,清空栈
    tt = 0;
    //从右向左扫一遍
    for (int i = n; i >= 1; i--) add(i);

    //找出结果
    for (int i = 1; i <= n; i++) ans = max(ans, s[i]);

    //输出
    printf("%d", ans);
    return 0;
}

三、STL栈法

#include <bits/stdc++.h>

using namespace std;
const int N = 1000010;

stack<int> stk; //栈
int a[N]; //高度数组
int b[N]; //能量数组
int s[N]; //每个发射塔的结果数组
int n;    //发射塔个数
int res;  //最大结果

/**
 * 功能:计算第i个发射塔,它可以给哪个发射塔带来能量
 * @param i
 */
void add(int i) {
    //把栈顶高度比自己小的出栈,这样的是不能享受i个发射塔带来的能量滴~
    while (!stk.empty() && a[i] > a[stk.top()]) stk.pop();
    //如果找着了一个高度比自己大的发射塔,那么,这个位置的发射塔将享受i个发射塔带来的能量。
    if (!stk.empty()) s[stk.top()] += b[i];
    //把自己入栈,等待其它人给自己带来能量,enjoy!
    stk.push(i);
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i] >> b[i];
    //从左向右扫一遍
    for (int i = 1; i <= n; i++) add(i);
    //清空栈
    while (!stk.empty()) stk.pop();
    //从右向左扫一遍
    for (int i = n; i >= 1; i--) add(i);
    //求最大值
    for (int i = 1; i <= n; i++) res = max(s[i], res);
    //输出
    printf("%d", res);
}
posted @   糖豆爸爸  阅读(82)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2019-09-10 明智的攻击
Live2D
点击右上角即可分享
微信分享提示