【模板】单调栈(P5788)
题目
题目描述:
给出项数为 n 的整数数列 a1…n。
定义函数 f(i) 代表数列中第 i 个元素之后第一个大于 ai 的元素的下标,即 f(i)=mini<j≤n,aj>ai{j}。若不存在,则 f(i)=0。
试求出 f(1…n)。
输入格式:
第一行一个正整数 n。
第二行 n 个正整数 a1…n。
输出格式:
一行 n 个整数表示 f(1),f(2),…,f(n) 的值。
数据范围与说明:
【数据规模与约定】
对于 30% 的数据,n≤100;
对于 60% 的数据,n≤5×103 ;
对于 100% 的数据,1≤n≤3×106,1≤ai≤109。
输入输出样例 #1
输入:
输出:
题意
给定一个长度为 n 的序列 a,定义 f(i) 为第 i 个元素之后第一个严格大于 ai 的元素下标,不存在则为 0。输出 f(1…n)。
思路
从右向左维护“严格递减”的单调栈:
- 栈中存储下标,且对应的值严格递减;
- 对于当前位置 i,不断弹出小于等于 ai 的下标,剩余的栈顶即为第一个更大的位置;
- 若栈为空,则 f(i)=0;
- 处理完后将 i 入栈继续向左。
时间复杂度 O(n)。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <bits/stdc++.h> using namespace std;
const int N = 3'000'000 + 5; int a[N], ans[N];
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int n; cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i];
stack<int> st; for (int i = n; i >= 1; --i) { while (!st.empty() && a[st.top()] <= a[i]) st.pop(); ans[i] = st.empty() ? 0 : st.top(); st.push(i); }
for (int i = 1; i <= n; ++i) { cout << ans[i] << (i == n ? '\n' : ' '); } return 0; }
|