单调栈

没什么东西,贴题

https://www.luogu.com.cn/problem/P5788
可以看到数据范围来到了106,n2暴力首先被pass

正解:单调栈
线性数据结构,思想很简单,从一段开始扫,对于这个题,从右往左,第一个先入栈
来到第二个,有两种情况,(1)第一个<第二个 (2)第一个>第二个(相等随便并入一个)
对于(1),很明显从此以后“第一个”不会成为答案,因为第二个要比第一个大,而后面再找最大值时,第二个肯定会被扫到,所以第一个没有必要留下了,弹栈
此时是特例,栈空了,但如果推广到其他情况,此时比当前数小的已经全部被弹了,因此栈首就是答案,但此时空了,所以第二个数的答案是0

对于(2),我们发现第一个就是答案,所以直接保存

由此可以得出程序思路:每到一个数,先拿它依次跟栈首对比,比它小就弹出,直到留下比它大的,这就是答案,然后入栈,以此类推
因为每次弹栈过后,栈都相当于被整理,于是栈内便是单调有序的

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#define MAXN 3000050
using namespace std;
int n,f[MAXN],ans[MAXN];
struct Node{
	int num,id;
}a[MAXN];
stack<Node> s;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].num;
		a[i].id=i;
	}
	ans[n]=0;
	s.push(a[n]);
	for(int i=n-1;i>=1;i--){
		while(!s.empty()&&a[i].num>=s.top().num){
			s.pop();
		}
		if(s.empty()){
			ans[i]=0;
		}else{
			ans[i]=s.top().id;
		}
		s.push(a[i]);
	}
	for(int i=1;i<=n;i++)	cout<<ans[i]<<' ';
	return 0;
}

注意坑,while弹栈的时候要加上是否栈空的判断,否则栈空时取top在评测时会RE

posted @ 2022-02-07 18:06  Cap1taL  阅读(44)  评论(0)    收藏  举报