【ssl2882】排队【单调栈模板】

Description

n个人排成一条直线(一排),给出队伍中每个人的身高,每个人只能看到站在他右边且个头比他小没有被其他人挡住(跟他身高相同也会挡出他)的人。请求出所有人可以看到的人数之和。
1<=N<=80,000

Sample Input

6    
10
3
7
4
12
2

Sample Output

5

分析

这题就是单调栈的模板题。

先来讲一下单调栈。
1、定义
单调栈是一种特殊的栈,其栈内的元素都保持一个单调性(单调递增或者递减)。

单调递增栈,从栈底到栈顶依次递增(单调非递减栈:允许有相等)
单调递减栈,从栈底到栈顶依次递减(单调非递增栈:允许有相等)
2、维护
维护单调栈的方式类似于维护单调队列。单调栈是单向进单向出,只要while依次判断栈顶的那个数是否符合栈的单调性,如果不符合就弹出,符合就把新的值压入栈。

用一个生活中的例子来模拟一下单调栈的维护过程
我们借用拿号排队的场景来说明下。现在有很多人在排队买可乐,每个人手里都拿着号,越靠前的人手里的号越小,但是号不一定是连续的。小明拿了号后并没有去排队,而是跑去约会了。等他回来后,发现队伍已经排得很长了,他不能直接插入到队伍里,不然人家以为他是来插队的。小明只能跑到队伍最后,挨个询问排队人手里的号,小明认为号比他大的人都是“插队”的,于是小明就会施魔法把这些人变消失,直到小明找到号比他小的为止。

在上面这个场景里,大家排的队伍就像是单调栈,因为大家手里拿的号是单调递增的。而小明找自己位置的这个过程就是元素加入单调栈的过程。新加入的元素如果加到栈顶后,如果栈里的元素不再是单调递增了,那么我们就删除加入前的栈顶元素,就像小明施魔法把“插队”的人变消失一样。直到新元素加入后,栈依然是单调递增时,我们才把元素加进栈里。

其他的详见注释。

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long n,a[100001],st[100001],top=1,ans;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	cin>>a[i];
    }
    a[n+1]=0x7fffffff; 
    st[1]=n+1;
    for(int i=n;i>=1;i--)//从右边开始
	{
		while(a[st[top]]<a[i]&&top>0)//升序序列,比原来的小就弹出,并且栈不为空
		{
			top--;//减掉就没了 
		} 
		ans+=st[top]-i-1;
		top++; 
		st[top]=i;
		/*此时栈顶的数是右边第一个大于等于a[i]的数,
		那么中间的数都比a[i]小,统计进答案st[++top]=i;*/
	} 
	cout<<ans;
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值