洛谷P5788 【模板】单调栈

题意:找到每个数后面第一个大于它的元素的下标

可以比喻成站了一队人,每个人向右看,求他们每个人看到的第一个人的位置

顾名思义,单调栈就是栈内元素具有单调性,其维护的就是一个数前/后第一个大于/小于他的数

我们将输入的数列a[]倒着遍历一下(要找每个数后面的第一个比它大的数,从后向前入栈可以实现),入栈的第一个数也就是数列的最后一个,它的对应函数值一定为0。倒数第二个入栈,和栈顶元素即它后面元素(即最后一个元素)相比,若比它大,栈顶元素就出栈,否则这个倒数第二个元素就正常入栈......

有一个问题是,这样就能保证求出的是第一个大于的数吗?

假设我们已经求出了ai的函数值fi,对于aj(aj<=ai)来说(只需考虑 j<i 的情况),ai一定不会对f1、f2、...、fj有影响,可能i对于aj是一个解,但也许在1...j-1中有更好的解。也就是O(n^2)暴力枚举的思想,找到一个比它大的数就退出;于是,我们对于整个序列都用贪心维护一个栈保存可能有用的元素下标,若栈顶对应元素比当前元素不大,贪心,然后弹出栈顶的下标。直到栈顶对应元素比当前元素大了,就说明不能继续贪心了,记录答案(重点,最靠前可行的元素就是栈顶对应的元素)。最后将当前下标加入栈。

#include <iostream>
#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn=3000001;
int a[maxn],f[maxn];

int main()
{
	int n;
	//cin>>n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]); //cin>>a[i];
	stack<int> s;
	int i=1;
	/*bool flag;//true means no one bigger than itself
	while(i<=n)
	{
		flag=true;
		s.push(a[i]);
		i++;
		for(int j=i;j<=n;j++)
		{
			if(a[j]>s.top())
			{
				flag=false;//not the "biggest"
				//cout<<j<<' ';
				printf("%d ",j);
				break;
			}
		}
		if(flag) printf("0 ");//cout<<0<<' ';
	}*/
	for(int i=n;i>=1;i--)
	{
		while(!s.empty()&&a[s.top()]<=a[i]) s.pop();
		f[i]=s.empty()?0:s.top();
		s.push(i);
	}
	for(int i=1;i<=n;i++) printf("%d ",f[i]);
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值