吃早饭
题目描述
同学们每天早上都会晨练,但是每次运动后都会很饿,于是他们回去吃早饭,
信奥班的同学们当然很有素质,他们都遵守规矩排队。每个同学都面向窗口,
一共有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;
}