• 【洛谷】【单调栈】P1901 发射站


    【题目描述:】

    某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发射站接收。

    显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,特别是为了安 全,每个发射站接收到的能量总和是我们很关心的问题。由于数据很多,现只需要你帮忙计 算出接收最多能量的发射站接收的能量是多少。

    【输入格式:】

    第 1 行:一个整数 N;

    第 2 到 N+1 行:第 i+1 行有两个整数 Hi 和 Vi,表示第 i 个人发射站的高度和发射的能量值。

    【输出格式:】

    输出仅一行,表示接收最多能量的发射站接收到的能量值,答案不超过 longint。



    [算法分析:]

    比较简单的想法是直接模拟:

    枚举(n)个发射站,

    同时第二层枚举这个发射站前后的发射站,枚举到比这个发射站高的站点就累加答案然后break.

    时间复杂度(O(n^2)),但是因为有break实际用时是要少一些的,大致能过七个点。

    但是可以使用单调队列来进行优化:

    先从前向后正序枚举发射站,把每个发射站都push_back进队列里,过程中如果队尾元素比此时元素(i)的高度要小,累加第(i)个发射站的答案,这是处理所有发射向右边的能量;

    再从后向前枚举,处理所有发射向左边的能量.

    最后所有发射站的能量最大值即为答案。

    只有back操作没有front操作的单调队列又被叫做单调栈



    ([Code:])

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    const int MAXN = 1000000 + 1;
    
    int n;
    int a[MAXN];
    struct Station {
    	int h, v;
    }h[MAXN];
    
    struct Node {
    	int h, pos;
    };
    deque<Node> q;
    
    inline int read() {
    	int x=0, f=1; char ch=getchar();
    	while(ch<'0' || ch>'9') {
    		if(ch == '-') f = -1;
    		ch = getchar();
    	}
    	while(ch>='0' && ch<='9')
    		x=(x<<3)+(x<<1)+ch-48, ch=getchar();
    	return x * f;
    }
    
    int main() {
    	n = read();
    	for(int i=1; i<=n; ++i)
    		h[i].h = read(), h[i].v = read();
    	for(int i=1; i<=n; ++i) {
            //使用while而不是if是处理这个发射站左边
            //所有高度比它低且最近的发射站向其发射的能量
    		while(!q.empty() && q.back().h < h[i].h) {
    			a[i] += h[q.back().pos].v;
    			q.pop_back();
    		}
    		q.push_back((Node){h[i].h, i});
    	}
    	while(!q.empty()) q.pop_back();
    	for(int i=n; i>=1; --i) {
    		while(!q.empty() && q.back().h < h[i].h) {
    			a[i] += h[q.back().pos].v;
    			q.pop_back();
    		}
    		q.push_back((Node){h[i].h, i});
    	}
    	int ans = 0;
    	for(int i=1; i<=n; ++i)
    		ans = max(ans, a[i]);
    	printf("%d
    ", ans);
    }
    
  • 相关阅读:
    Eclipse汉化后怎么改回英文版 (中文 改 英文)
    解决android中Layout文件下的xml文件配好后,R类中不能自动生成相应代码
    Android SDK离线安装
    Windows环境下Android Studio v1.0安装教程
    Eclipse调试Bug的七种常用技巧
    博客开通了
    Android常见的按钮监听器实现方式
    用setTimeout实现在DOM上(通常是菜单栏)鼠标停留一段时间才执行相应的操作
    Javascript模块模式学习分享
    Oracle数据库逻辑存储结构管理
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9074376.html
Copyright © 2020-2023  润新知