今天主要练习了单调队列和单调栈的题,尤其是单调队列虽然原理简单,但用代码实现过程却不容易理解,因为它的队首和队尾都可以操作,灵活性很大。
首先来看一下单调队列的原理:
1入队,得到队列(1);
3入队,得到队列(1,3);
2入队,这时,队尾的的元素3>2,将3从队尾弹出,新的队尾元素1<2,不用弹出,将2入队,得到队列(1,2);
1入队,2>1,将2从队尾弹出,得到队列(1,1);
5入队,得到队列(1,1,5);
然后是单调栈的原理:
单调栈与单调队列很相似。首先栈是后进先出的,单调性指的是严格的递增或者递减。
单调栈有以下两个性质:
1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。
2、越靠近栈顶的元素越后进栈。
单调栈与单调队列不同的地方在于栈只能在栈顶操作,因此一般在应用单调栈的地方不限定它的大小,否则会造成元素无法进栈。
元素进栈过程:对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。对于单调递减栈,则每次弹出的是大于e或者等于e的元素。
举个栗子:
一个单调递增栈的例子:
进栈元素分别为3,4,2,6,4,5,2,3
3进栈:(3)
3出栈,4进栈:(4)
2进栈:(4,2)
2出栈,4出栈,6进栈:(6)
4进栈:(6,4)
4出栈,5进栈:(6,5)
2进栈:(6,5,2)
2出栈,3进栈:(6,5,3)
以上左端为栈底,右端为栈顶。
附一道今天做的题:
Bad Hair Day
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 72 Accepted Submission(s) : 31
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.
AC代码及注释:
/*
题意:牛排队排好,每个牛只能看到比它高度严格低的牛,问所有的牛能看到的个数
思路:换个思路,求每个牛能被看到多少次,加起来,和题目要求的结果是一样的,单调递增栈:(网路上大神的思路,膜拜)
*/
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
typedef long long ll;
int main()
{ int n,i,a;
while(~scanf("%d",&n))
{ll ans=0;
stack<int> q;
for(i=1;i<=n;i++)
{
scanf("%d",&a);
while(q.size()&&q.top()<=a) q.pop();//比这个牛低的肯定看不到这个牛以及它以后的牛,所以弹出
ans+=q.size();//栈里面的牛的个数都能看到这个牛
q.push(a);
}
printf("%lld\n",ans);
}
return 0;
}
对了,明天又要做练习赛了,希望明天对我好一点~~~