单调栈模板(单调栈)

测试链接:https://www.nowcoder.com/practice/2a2c00e7a88a498693568cef63a4b7bb

思路

先用数组创建一个栈,但数组严格单调上升时候直接入栈,当出现下一个数小于等于的情况时候,出栈更新答案,第一遍遍历数组后,单调栈还存在一些数,接下来将单调栈的数字依次弹出,单调栈的顶部的右边答案显然一定为-1,只需要考虑左边界问题,当单调栈还不为空时候,左边第一个最小值就是压栈的数字,当栈内只剩下一个数字时候,那么这个数字的左右答案就均为-1,而最后从后往前处理相同值情况,可以保证只需要一次传递就可以更新不同的答案,如果从前往后可能会出现需要更新多次的情况。

题解

#include <bits/stdc++.h>
#include <unistd.h>
using namespace std;
const int N=1e6+10;
int ans[N][2];
int stk[N];
int a[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    int r=0; 
    for(int i=0;i<n;i++)
    {
        while(r>0&&a[stk[r-1]]>=a[i])
        {
            int cur = stk[--r];
            ans[cur][0]= r>0?stk[r-1]:-1;
            ans[cur][1] = i;
        }
        stk[r++]=i;
    }
    while(r>0)
    {
        int cur = stk[--r];
        ans[cur][1]=-1;
        ans[cur][0]=r>0?stk[r-1]:-1;
    }

    for(int i=n-2;i>=0;i--)
    {
        if(ans[i][1]!=-1&&a[i]==a[ans[i][1]])ans[i][1]=ans[ans[i][1]][1];
    }

    for(int i=0;i<n;i++)cout<<ans[i][0]<<' '<<ans[i][1]<<endl;

    return 0;
}

洛谷模板

测试链接:https://www.luogu.com.cn/record/222806264

#include <bits/stdc++.h>
using namespace std;
const int N=3e6+10;
typedef long long ll;
int t,n;
int stk[N];
int ans[N];
ll a[N];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=n;i++)cin>>a[i];
    int r=1;
    for(int i=1;i<=n;i++)
    {
        while(r>1&&a[i]>a[stk[r-1]])
        {
            int cur = stk[--r];
            ans[cur] = i;
        }
        stk[r++]=i;
    }
    for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
    cout<<endl;


    return 0;
}
posted @ 2025-07-07 15:39  屈臣  阅读(8)  评论(0)    收藏  举报