集训第十五天(2017/8/14):单调队列&单调栈

       今天主要练习了单调队列和单调栈的题,尤其是单调队列虽然原理简单,但用代码实现过程却不容易理解,因为它的队首和队尾都可以操作,灵活性很大。

       首先来看一下单调队列的原理:

     • 队列中 元素 之间的 关系 具有 单调性(可以是单调不增加或单调不减小,也就是说可以有重复,每个元素不必严格单调) ,而且, 队首和队尾 都可以进行 出队操作 ,只有队尾可以进行 入队 操作。
     • 单调队列的常用操作如下:
     • 1 )插入:若新元素从队尾插入后会 破坏 单调性,则 删除 队尾元素,直到插入后不再破坏单调性为止,再将其插  入单调队列。
     • 2 )获取最优(最大、最小)值:访问首尾元素。
举个栗子:
    一组数( 1 3 2 1 5 6 ),进入单调 不减队列 的过程

1入队,得到队列(1);

3入队,得到队列(13);

2入队,这时,队尾的的元素3>2,将3从队尾弹出,新的队尾元素1<2,不用弹出,将2入队,得到队列(12);

1入队,2>1,将2从队尾弹出,得到队列(11);

5入队,得到队列(115);

6 入队,得到队列( 1 1 5 6 );
 关于单调队列的经典例题广告印刷/Largest Rectangle in a Histogram我专门写了一篇结题报告,很详细,有兴趣的可以看看。

         然后是单调栈的原理:

       单调栈与单调队列很相似。首先栈是后进先出的,单调性指的是严格的递增或者递减。

       单调栈有以下两个性质:

       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
Problem Description

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 ≤ h≤ 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, <i>N</i>. <br>Lines 2..N+1: Line <i>i</i>+1 contains a single integer that is the height of cow <i>i</i>.
 


 

Output
Line 1: A single integer that is the sum of <i>c</i><sub>1</sub> through <i>c<sub>N</sub></i>.

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

对了,明天又要做练习赛了,希望明天对我好一点~~~

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值