题解:洛谷 P5788 【模板】单调栈

【题目来源】

洛谷:P5788 【模板】单调栈 - 洛谷

【题目描述】

给出项数为 \(n\) 的整数数列 \(a_{1...n}\)

定义函数 \(f(i)\) 代表数列中第 \(i\) 个元素之后第一个大于 \(a_i\) 的元素的下标,即 \(f(i)=min_{⁡i<j≤n,a_j>a_i}\{j\}\)。若不存在,则 \(f(i)=0\)

试求出 \(f(1…n)\)

【输入】

第一行一个正整数 \(n\)

第二行 nn 个正整数 \(a_{1…n}\)

【输出】

一行 \(n\) 个整数表示 \(f(1),f(2),…,f(n)\) 的值。

【输入样例】

5
1 4 2 3 5

【输出样例】

2 5 4 5 0

【算法标签】

《洛谷 P5788 单调栈》 #线性数据结构# #栈# #单调栈# #模板题#

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 3000005;  // 数组大小常量
int n, a[N], ans[N], q[N];  // a: 输入数组, ans: 结果数组, q: 单调栈

int main()
{
    scanf("%d", &n);  // 读入数组长度
    
    // 读入数组元素
    for (int i = 1; i <= n; i++) 
        scanf("%d", &a[i]);
    
    int top = 0;  // 栈顶指针,栈空时top=0
    
    // 从前往后遍历数组
    for (int i = 1; i <= n; i++) {
        // 当栈非空且当前元素大于栈顶元素时
        while (top > 0 && a[q[top]] < a[i]) {
            ans[q[top]] = i;  // 记录栈顶元素的答案:第一个比它大的元素位置
            top--;  // 弹出栈顶
        }
        q[++top] = i;  // 将当前位置入栈
    }
    
    // 输出结果
    for (int i = 1; i <= n; i++) 
        printf("%d ", ans[i]);
    
    return 0;
}
// 使用acwing模板二刷
#include <bits/stdc++.h>
using namespace std;
const int N = 3000006;  // 定义数组大小,略大于3×10^6
int n, a[N], ans[N], stk[N], tt;  // a: 输入数组, ans: 结果数组, stk: 单调栈, tt: 栈顶指针

int main()
{
    cin >> n;  // 读入数组长度
    
    // 读入数组元素
    for (int i = 1; i <= n; i++) 
        cin >> a[i];
    
    // 单调栈算法
    for (int i = 1; i <= n; i++)
    {
        // 当栈不为空且当前元素大于栈顶元素时
        while (tt && a[stk[tt]] < a[i]) 
        {
            ans[stk[tt]] = i;  // 记录栈顶元素的下一个更大元素位置
            tt--;  // 弹出栈顶
        }
        stk[++tt] = i;  // 将当前索引入栈
    }
    
    // 输出结果
    for (int i = 1; i <= n; i++) 
        cout << ans[i] << " ";
    cout << endl;
    
    return 0;
}

【运行结果】

5
1 4 2 3 5
2 5 4 5 0
posted @ 2026-03-14 18:26  团爸讲算法  阅读(2)  评论(0)    收藏  举报