单调栈

这个神奇的东西,我咕了好久好久

首先,顾名思义,这个数据结构是个栈,且栈内从栈顶到栈底,一定是单调的。

Q:“道理我都懂,他能干啥?”

A:“$O(n)$求一个数前/后第一个大于/小于他的数。”

Q:“这怎么办呢?"

A:“看这道例题。”

A:“我们维护这个栈,从后往前扫,对于当前的元素,如果栈顶元素小于等于他,就弹出来,一直弹到合法或栈空,那么留下来的不就是第一个大于他的数辣~,然后当前元素入栈即可。”

Q:“这样为什么是对的呢?”

 

 观察这组数据,问题转化为在该位置的人抬头可以看见的最近的人。

所以显然小于等于他且在他右边的人是没有用的,扔掉。

那么不会出现我把最近的比我高的给弹掉了,答案错误吗?

当然不会,首先要明确,轮到我的时候,我的右边一定在栈里面,既然他在栈里面了,假设他比我们大,那肯定是合法答案,那他不超过我们,我们就会弹(其实不难发现是会弹空的,因为我们的栈从栈底到栈顶是严格递增的)。

话不多说,show me the code。

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<vector>
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i<b;++i)
using namespace std;
template <typename T>
inline void read(T &x){
    x=0;char ch=getchar();bool f=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    if(f)x=-x;
}
template <typename T,typename ...Args>
inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);}
const int N = 3e6 + 5;
int n,a[N],ans[N],s[N],top;
#define now s[top]
signed main(){
    read(n);
    rep(i,1,n)read(a[i]);
    for(int i=n;i>=1;--i){
        while(a[i] >= a[now] && top)top--;
        ans[i] = now;
        s[++top] = i;
    }
    rep(i,1,n)printf("%d ",ans[i]);
}

 

posted @ 2022-04-30 20:29  Xu_brezza  阅读(32)  评论(2编辑  收藏  举报