一、 题目描述
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:
=
= =
= - = Cows facing right -->
= = =
= - = = =
= = = = = =
1 2 3 4 5 6
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.
Input:
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.
Output:
Line 1: A single integer that is the sum of c1 through cN.
Sample Input:
6
10
3
7
4
12
2
Sample Output:
5
二、解题思路
本题是单调栈的经典问题。从第一头奶牛开始,若栈为空,则进栈,若当前元素大于或等于栈顶的元素,则栈顶元素出栈,直至栈顶当前元素小于栈顶元素时,将当前元素入栈,每一次入栈后,需要将结果加上栈顶元素当前的位置索引(默认数组首元素为0)。
为什么要每一次进栈时,要将结果加上栈顶元素当前的位置索引呢?
我们要求的是,对于每一头牛而言,能看到的牛的数量的总和,例如 若栈中已有元素 10、5、3 此时元素2入栈,元素2成为新的栈顶元素,其位置下标为3,那么对结果进行+3操作的意义为,身高为10、5、3的这三头牛都能看见身高为2的这头牛。此时栈内的元素为 10、5、3、2.此时元素7要进行入栈,但因为当前栈顶的元素为2,小于7,所以要将2先出栈(其意义为身高为2的牛看不见身高为7的牛,且身高为7的牛之后的所有牛,都看不见,故身高为2的牛已经无法再对最终结果造成影响,所以出栈)此时栈顶元素变为3,同理出栈,接下来栈顶元素变为5,出栈,接下来栈顶元素变为10,由于10>7,故7入栈,此时7成为新的栈顶元素它的下标为1,对结果进行+1操作,其意义为只有身高为10的这头牛能看到7。**之所以10>7就不会出栈,是因为身高为10的这头牛任然可以对最终的结果造成影响。**若此时再来一头身高为12的牛,则当前栈中的所有元素都要出栈,因为10、7无法看到12,亦无法看到12之后的任何牛,故它们此时已对最终的结果无法造成任何影响,所以均出栈。
三、ac代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
int N;
int top = -1, a = 0;
long long ans = 0;
scanf("%d", &N);
long long int *h = (long long int *)malloc( (N + 10) * sizeof(long long int) );
///
while (N--) {
scanf("%d", &a);
if (top == -1) {
h[++top] = a;
continue;
}
while (a >= h[top]) {
top --;
}
if (a < h[top]) {
h[++top] = a;
ans += top;
printf("ans = %lld\n", ans);
}
}
printf("%lld", ans);
free(h);
return 0;
}
值得说明的是:
- 尽管题目中说每头牛的身高范围在int的取值范围之中,但如果动态分配的数组为int型则会报错,若换成long long则不会报错。同样,如果直接开一个大小为80010的long long型数组不会报错,若是int型,则会报错。
2.存储答案的ans变量应定义为long long,若定义为int型,则会报错。