农夫约翰有N(N≤80000)头奶牛正在过乱头发节。每一头牛都站在同一排面朝东方,而且每一头牛的身高为
。第NNN头牛在最前面,而第111头牛在最后面。 对于第i头牛前面的第j头牛,如果
并且
那么认为第i头牛可以看到第i+1到第j头牛。
定义
为第i头牛所能看到的别的牛的头发的数量。请帮助农夫约翰求出
Some of Farmer John’s N cows (1 ≤ N ≤ 80,000) are having a bad hair day! Since each cow is self-conscious about her messy hairstyle, FJ wants to count the number of other cows that can see the top of other cows’ heads.
Each cow i has a specified height hi (1 ≤ hi ≤ 1,000,000,000) and is standing in a line of cows all facing east (to the right in our diagrams). Therefore, cow i can see the tops of the heads of cows in front of her (namely cows i+1, i+2, and so on), for as long as these cows are strictly shorter than cow i.
Consider this example:
-
- -
- - -
- - -
- - - - -
- - - - - -
1 2 3 4 5 6
Cows facing right -->
Cow#1 can see the hairstyle of cows #2, 3, 4
Cow#2 can see no cow’s hairstyle
Cow#3 can see the hairstyle of cow #4
Cow#4 can see no cow’s hairstyle
Cow#5 can see the hairstyle of cow 6
Cow#6 can see no cows at all!
Let ci denote the number of cows whose hairstyle is visible from cow i; please compute the sum of c1 through cN.For this example, the desired is answer 3 + 0 + 1 + 0 + 1 + 0 = 5.
Line 1: The number of cows, N.
Lines 2…N+1: Line i+1 contains a single integer that is the height of cow i.
Line 1: A single integer that is the sum of c1 through cN.
6
10
3
7
4
12
2
5
仔细阅读题目,题目要求没头牛能看到的牛的数量的总和。分析下样例。
10 3 7 4 12 2
一次计算每头牛能看到的牛。
10: 3、 7、 4,能看到3头牛,之所以没有2,是因为v中间有个12,挡住了2。
3:一个都看不到。
7:4,能看到1头牛。
4:一个都看不到。
12:2,能看到1头牛。
2:一个都看不到。
总数为3+1+1=5 。
看起来只要从后往前扫,求出比h[i]
小的数即可。但是这样做存在一个问题,该问题在样例中也有体现,即会出现“遮挡”的情况,比如样例中的2会被12给遮挡。而如果加入“遮挡”的计算起来会过于复杂。
此时可以更换一个思路,从原来的统计比h[i]
小、且未被遮挡的元素个数改为统计能未遮挡的看到h[i]
的元素个数。
更换思路之后,问题就变成了统计1∼i−1范围内的未遮挡的单调减的元素个数。这部分我们可以采用单调栈的思想进行实现。
单调栈,就是栈中元素具有单调性,例如单调增或单调减。
每次将栈顶元素不断和当前元素进行比较,若栈顶元素小于等于当前元素则进行出栈,不断重复,直到栈中元素能与当前元素构成一个具有单调减性质的序列。
while(!s.empty()&&s.top()<=x){
s.pop();
}
最终答案就是累加每个元素能被看到的元素数量的总和。
#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
const int N=8e4+5;
typedef long long ll;
stack<int> s;//定义栈
int main(){
int n,x;
ll sum=0;//最终的总和
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
while(!s.empty()&&s.top()<=x){//不断将<=x的元素出栈
s.pop();
}
sum+=s.size();//累加能看到x的元素个数
s.push(x);//栈中元素呈单调减
}
cout<<sum;
return 0;
}
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=gij8phtm31ao
Q.E.D.