题目链接:https://www.luogu.com.cn/problem/P2947
题目大意:
约翰的 (N(1 le N le 10^5)) 头奶牛站成一排,奶牛(i)的身高是(H_i(l le H_i le 1,000,000)).现在,每只奶牛都在向右看齐.对于奶牛(i),如果奶牛(j)满足 (i lt j) 且 (H_i lt H_j) ,我们可以说奶牛(i)可以仰望奶牛(j) . 求出每只奶牛离她最近的仰望对象.
解题思路:
维护一个单调非递增的 单调队列 ,然后每次在第 (i) 投奶牛入队列之前,判断对位元素是否要出队,如果要出队,则对位元素的仰望对象就是 (i)。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, h[maxn], target[maxn];
deque<int> que;
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> h[i];
for (int i = 1; i <= n; i ++) {
while (!que.empty() && h[que.back()] < h[i]) {
target[que.back()] = i;
que.pop_back();
}
que.push_back(i);
}
for (int i = 1; i <= n; i ++) cout << target[i] << endl;
return 0;
}
因为进出元素都是队尾执行,所以我们可以用 单调栈 来实现同样的功能。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, h[maxn], target[maxn];
stack<int> stk;
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> h[i];
for (int i = 1; i <= n; i ++) {
while (!stk.empty() && h[stk.top()] < h[i]) {
target[stk.top()] = i;
stk.pop();
}
stk.push(i);
}
for (int i = 1; i <= n; i ++) cout << target[i] << endl;
return 0;
}