发射站(2017佛山市选拔初中组)

发射站(2017佛山市选拔初中组)

题目描述

有N个能量发射站排成一行,每个发射站i都有不相同的高度 Hi,并能向两边(当然两端的只能向一边)同时发射能量值为Vi的能量,并且发出的能量只被两边最近的且比它高的发射站接收。
显然每个发射站发来的能量有可能被0或1或2个其它发射站接收,特别是为了安全,它受到的能量总和是我们很关心的。由于数据很多,请你帮助我们计算出接受了最多能量的发射站接受的能量是多少。
【数据范围】
1≤N≤800,000;1≤hi≤2,000,000,000;1≤vi≤10,000。

输入格式 1756.in

第1行:一个整数 N;
第2..N+1行:第i+1行有2个整数Hi和Vi,表示第i个发射站的高和发射的能量值。

输出格式 1756.out

一行:一个发射站接收到的最大能量值。

输入样例 1756.in

3
4 2
3 5
6 10

输出样例 1756.out

【提示】
第3个发射站可接受第1和第2个发射的能量:2+5=7

【输入样例2】
4
1 2
3 1
7 5
2 3
【输出样例2】
4
【提示】

  

第三个发射站可接受第2个和第四个发射的能量 :1+3=4

 

  这一题其实在暴力的基础上加一点小的优化就可以A。

  其实就是要找前(后)比当前(now)高的第一个。当我们从左往右找的时候,其实就已经是计算出前面的了。那么如果前一个比now高,那么就是前一个;否则,那比前面还矮的就不必搜索了,因为既然你比前面的高,比前面矮的自然也不会比now高。所以,我们可以记录下每一个比它高的那个的位置l和r。

  在now时,直接由l[now-1]往前找就可以了,可以省去很多时间,同样的,也从右往左扫一遍,最后取一个能量max值就是最终结果。

  参考代码:

#include<iostream>
#include<cstdio>
using namespace std;
int n,h[800005],m[800005];
int l[800005],r[800005],ans[800005],oo=2000000005;
int main()
{
	freopen("1756.in","r",stdin);
	freopen("1756.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>h[i]>>m[i];
	h[0]=oo;
	h[n+1]=oo;
	for(int i=1;i<=n;i++)
	{
		int v=0;
		if(h[i]<h[i-1]) 
		{
			l[i]=i-1;
			ans[i-1]+=m[i];
		}
		else
		{
			v=l[i-1];
			for(int j=v;j>=1;j--)
			{
				if(h[i]<h[j])
				{
					l[i]=j;
					ans[j]+=m[i];
					break;
				}
			}
		}
	}
	for(int i=n;i>=1;i--)
	{
		int v=0;
		if(h[i]<h[i+1]) 
		{
			r[i]=i+1;
			ans[i+1]+=m[i];
		}

    else
		{
			v=r[i+1];
			for(int j=v;j<=n;j++)
			{
				if(h[i]<h[j])
				{
					r[i]=j;
					ans[j]+=m[i];
					break;
				}
			}
		}
	}
	int ans2=0;
	for(int i=1;i<=n;i++)
	{
		ans2=max(ans2,ans[i]);
	}
	cout<<ans2<<endl;
	return 0;
}

  

转载于:https://www.cnblogs.com/yiyiyizqy/p/7397070.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值