单调栈的应用,结合二分查找
单调栈可以获得比第一个比当前数大/小的数的位置。
使用deque也可以用来二分查找。
如下例题:
https://codeforces.com/contest/1696/problem/D
可以存储当前数的单调增栈和单调减栈,然后根据栈中首元素的相对位置,进行选择和二分查找。

#include<bits/stdc++.h> using namespace std; typedef long long LL; void YD(LL T) { LL n; cin >> n; vector<LL> nums(n); for (int i = 0; i < n; i++) cin >> nums[i]; vector<LL> to_node(n); deque<int> up; deque<int> down; up.push_back(n - 1); down.push_back(n - 1); for (int i = n - 2; i >= 0; i--) { int num = nums[i]; while (up.size() && num > nums[up.front()]) up.pop_front(); while (down.size() && num < nums[down.front()]) down.pop_front(); if (up.size() == 0) to_node[i] = down.back(); else if (down.size() == 0)to_node[i] = up.back(); else { if (up.front() > down.front()) { int l = 0, r = down.size() - 1; while (l < r) { int mid = (l + r + 1) / 2; if (down[mid] < up.front()) l = mid; else r = mid - 1; } to_node[i] = down[l]; } else { int l = 0, r = up.size() - 1; while (l < r) { int mid = (l + r + 1) / 2; if (up[mid] < down.front()) l = mid; else r = mid - 1; } to_node[i] = up[l]; } } up.push_front(i); down.push_front(i); } int cur = 0; int res = 0; while (cur != n - 1) { cur = to_node[cur]; res++; } cout << res << endl; } int main() { int T = 1; cin >> T; while (T--) { YD(T); } return 0; }

#include<bits/stdc++.h> using namespace std; typedef long long LL; int nums[300010]; int prev_max[300010]; int next_max[300010]; int prev_min[300010]; int next_min[300010]; int Dis(int left, int right, bool to_left) { if (left == right) return 0; if (left + 1 == right) return 1; if (to_left) { if (right == prev_min[right]) { return Dis(left, prev_max[right], true)+1; } else { return Dis(left, prev_min[right], true)+1; } } else { if (left == next_min[left]) { return Dis(next_max[left],right, false) + 1; } else { return Dis(next_min[left], right, false) + 1; } } } void YD() { int n; cin >> n; for (int i = 1; i <= n; i++) { cin >> nums[i]; } prev_max[1] = prev_min[1] = 1; int cur_max = 1; int cur_min = 1; for (int i = 2; i <= n; i++) { if (nums[i] > nums[cur_max]) cur_max = i; if (nums[i] < nums[cur_min]) cur_min = i; prev_max[i] = cur_max; prev_min[i] = cur_min; } next_max[n] = next_min[n] = n; cur_max = n; cur_min = n; for (int i = n-1; i >=1; i--) { if (nums[i] > nums[cur_max]) cur_max = i; if (nums[i] < nums[cur_min]) cur_min = i; next_max[i] = cur_max; next_min[i] = cur_min; } int max_index = prev_max[n]; int res = Dis(1, max_index, true)+Dis(max_index,n,false); cout << res << endl; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int T = 1; cin >> T; while (T--) { YD(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人