发射站
问题描述
某地的 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] 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;
}