Bad Hair Day (单调栈)(C语言)

一、 题目描述

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;
 } 

值得说明的是:

  1. 尽管题目中说每头牛的身高范围在int的取值范围之中,但如果动态分配的数组为int型则会报错,若换成long long则不会报错。同样,如果直接开一个大小为80010的long long型数组不会报错,若是int型,则会报错。
    2.存储答案的ans变量应定义为long long,若定义为int型,则会报错。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值