题解:洛谷 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
浙公网安备 33010602011771号