zoukankan      html  css  js  c++  java
  • P1901 发射站

    题目传送门

    一、解题思路

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

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

    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);
    }
    
  • 相关阅读:
    Redis安装-Redis常用命令-redis.conf配置信息总结
    JVM--心得 OOM时的堆信息获取与分析
    JVM--心得 堆栈区域和GC的设置
    JVM--心得(加载 链接 初始化)
    JVM--心得概念
    我的Python之路:找一个幸运数
    springboot模板
    spring boot入门
    java自定义注解
    git集成idea
  • 原文地址:https://www.cnblogs.com/littlehb/p/15249812.html
Copyright © 2011-2022 走看看