吃早饭

吃早饭

题目描述

同学们每天早上都会晨练,但是每次运动后都会很饿,于是他们回去吃早饭,
信奥班的同学们当然很有素质,他们都遵守规矩排队。每个同学都面向窗口,
一共有N个同学。现在XJ想知道每个同学能够看到的前面的同学的个数和是多少。
定义一个同学能够看到的人为在他前面且身高严格低于他的人,并且他的视线
会被在他前面第一个身高大于等于他的人挡住。也就是说无论如何也无法看到再
前面的人了。~~哪怕是郭敬明。~~ 

输入

N+1行
第一行一个正整数N表示同学的个数。
以下N行分别表示从后到前(窗口)同学的身高a.

输出

一行一个整数,表示所有同学能看到的人的个数和。

样例输入

6
10
3
7
4
12
2

样例输出

5

提示:

数据范围 30% 1<=N<=100,
100% 1<=N<=80000,1<=a<=1000000000.

分析:

搜索+贪心优化,
sf[i]表示第i个人最远看到的那个人,从后往前搜,如果i能看到第j个人,那么一定能看到j能看到的所有人,则直接跳到j最远看到的那个人继续判断,这样将大大优化时间。

源代码:

#include <bits/stdc++.h>
using namespace std;
long long n,h[180010],f[180010],r[180010],ans=0;
int main() {
	cin>>n;
	for(int i=1; i<=n; i++) cin>>h[i];
	for(int i=n; i>0; i--) {
		int j=i+1;
		while(j<n+1&&h[i]>h[j]) j=r[j];
		r[i]=j;
		f[i]=j-i-1;
	}
	for(int i=1; i<=n; i++) ans+=f[i];
	cout<<ans<<endl;
	return 0;
}

AC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值