发射站(HGOI)

发射站

问题描述

某地的 N 个能量发射站排成一行,每个发射站 i,有互相不同高度 hi,并能向两边(端点处只能
向一边)同时发射能量值为 vi 的能量,且发出的能量只能被两边最近的且比它高的发射站接收。
显然,每个发射站发来的能量有可能被 0 至 2 个其它的发射站所接收。为了安全,我们关心每个
发射站接收到的能量总和。由于数据很大,需要你计算出接收能量最多的发射站接收的能量是多少。

输入

第 1 行:一个整数 N;
每 2 到 N+1 行:每行有两个整数 hi 和 vi,表示第 i 个发射站的高度和发射的能量值。

输出

只有一行,表示最多的能量值,答案不超过 32bit 的整数

数据规模

对于 40%的数据,1 N 5000,1 h 100000,1 v 10000;
对于 70%的数据,1 N 100000,1 h 2,000,000,000;1 v 10000;
对于 100%的数据,1 N 1000000,1 h 2,000,000,000;1 v 10000。

算法

  • 讲真,这真的真的是一道大水题。
  • 首先从题目上来看,对于任意一个点,只有左右两边的比他高的最近的点能够接收到他的信号,那么只要有一条单调递减的数列来实现,那么就可以用栈来维护
  • 栈内的结构如下:栈底到栈顶的数据时单调递增的,对于数据 h [ i ] 来说,栈前面的所有数比他小都要出栈(同时对于后面的数,当前的 h [ i ] 也是相对最近的较高的数),直到找到比他大的数,而这一个数就是所要接受的。
  • 上面是向前释放的,对于向后释放的我刚开始是打算正反做两遍,但在模拟的时候惊奇的发现,当你弹出栈的时候,出栈的数所遇见的 h [ i ] 就是理他最近的比他大的数(不然早就出栈了),那么很荣幸的优化到(O)N算法,然后就AK了:)
  • 实力水题难得一遇

#include <stdio.h>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
void ff(){
    freopen("station.in","r",stdin);
    freopen("station.out","w",stdout);
}
const int MAXN=1000100;
int n,maxx=0;
struct node{
    int sum,num;
    int v,h;
    node(){
        sum=0;
    }
}a[MAXN];
deque<node> q;
int main(){
    ff();
    scanf("%d",&n);
    scanf("%d%d",&a[1].h,&a[1].v);
    a[1].num=1;
    q.clear();
    q.push_back(a[1]);
    for (int i=2;i<=n;i++){
        scanf("%d%d",&a[i].h,&a[i].v);
        a[i].num=i;
        while(!q.empty()&&q.back().h<=a[i].h){
            if(q.back().h<a[i].h){
                node t=q.back();
                a[i].sum+=a[t.num].v;
                maxx=max(maxx,a[i].sum);
            }
            q.pop_back();
        }
        if(!q.empty()){
            node temp=q.back();
            a[temp.num].sum+=a[i].v;
            maxx=max(maxx,a[temp.num].sum);
        }
        q.push_back(a[i]);
    }
    cout<<maxx;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42037034/article/details/80469020