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

核心思想

使用一个 单调递减栈 来维护尚未找到“下一个更大元素”的元素下标。

  • 遍历数组时,如果当前元素 a[i]大于 栈顶元素对应的值 a[top],说明找到了栈顶元素的“下一个更大元素”,即 f(top) = i。
  • 将栈顶弹出,并继续检查新的栈顶,直到栈空或栈顶对应值 ≥ 当前值。
  • 最后将当前下标 i 入栈。

遍历结束后,栈中剩余的下标都没有找到更大的元素,对应答案为 0。

为什么用单调栈?

  • 暴力做法是 O(n^2),对于 n=3*10^6 显然超时。
  • 单调栈可以在线性时间内解决该问题,时间复杂度为 O(n),每个元素最多入栈和出栈一次。

代码详解(C++)

#include<iostream>
#include<stack>
#include<vector>
using namespace std;

int n;
vector<int> vec(3000001, 0);   // 存储原数组(1-indexed)
vector<int> ans(3000001, 0);   // 存储答案 f(i)

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> vec[i];

    stack<int> S;  // 存放下标,维护单调递减(按值)

    for (int i = 1; i <= n; i++) {
        // 当前元素 vec[i] 比栈顶元素大 → 找到栈顶的“下一个更大”
        while (!S.empty() && vec[i] > vec[S.top()]) {
            ans[S.top()] = i;  // 记录答案
            S.pop();           // 弹出已处理的下标
        }
        S.push(i);  // 当前下标入栈
    }

    // 栈中剩余元素没有更大的,答案为 0(初始化已为0,可省略)
    while (!S.empty()) {
        ans[S.top()] = 0;
        S.pop();
    }

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

复杂度分析

  • 时间复杂度:O(n)每个元素入栈、出栈各一次。
  • 空间复杂度:O(n)用于存储数组、答案和栈。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务