zoukankan      html  css  js  c++  java
  • 【洛谷】【单调栈】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);
    }
    
  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9074376.html
Copyright © 2011-2022 走看看