题目情境#
题目链接:https://www.luogu.com.cn/problem/P5788 ↗
题目描述
给出项数为 的整数数列 。
定义函数 代表数列中第 个元素之后第一个大于 的元素的下标,即 。若不存在,则 。
试求出 。
输入格式
第一行一个正整数 。
第二行 个正整数 。
输出格式
一行 个整数表示 的值。
输入输出样例
输入 #1
5
1 4 2 3 5plaintext输出 #1
2 5 4 5 0plaintext对于 的数据,,。
算法解析#
单调栈是一种维护元素单调性的栈结构,用于高效求解”下一个更大/更小元素”类问题。
核心思路: 从右向左遍历数组,维护一个单调递减栈(栈底到栈顶递减),栈中存储下标。
对于每个位置 :
- 弹出栈中所有值 的元素(它们不可能成为 左侧任何元素的答案);
- 若栈非空,则栈顶下标即为 (第一个大于 的元素);
- 将 压入栈中。
复杂度: 每个元素至多入栈、出栈各一次,时间复杂度为 ,空间复杂度为 。
Python代码实现#
n = int(input())
a = list(map(int, input().split()))
f = [0] * n
q = []
for i in range(n - 1, -1, -1):
while q and a[q[-1]] < a[i]:
q.pop()
if q:
f[i] = q[-1]
q.append(i)
print(*f)pythonC++代码实现#
#include <cstdio>
using namespace std;
const int N = 3000005;
int a[N], f[N], stk[N];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int top = 0;
// 从右往左,维护单调递减栈,求每个位置右边第一个更大元素的下标
for (int i = n; i >= 1; i--) {
while (top && a[stk[top]] <= a[i]) top--; // 弹出所有不大于 a[i] 的元素
f[i] = top ? stk[top] : 0; // 栈顶即答案,空栈则为 0
stk[++top] = i; // 当前下标入栈
}
for (int i = 1; i <= n; i++) printf("%d ", f[i]);
return 0;
}cpp