【算法模板】数据布局:单调栈

[复制链接]
发表于 2026-2-10 14:27:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
算法头脑

单调栈的焦点头脑是通过维护一个栈,使得栈内元素保持某种单调性(递增或递减),从而在遍历数组时可以快速确定当前元素相干的特定信息,如下一个更大元素、前一个更小元素等。具体的单调性取决于题目需求:


  • 单调递增栈:栈内元素从栈底到栈顶保持递增次序(即栈顶元素最小)。这种栈适适用于探求某个元素的下一个更大元素上一个更小元素
  • 单调递减栈:栈内元素从栈底到栈顶保持递减次序(即栈顶元素最大)。这种栈适适用于探求某个元素的下一个更小元素上一个更大元素
算法流程

探求下一个更大元素为例,算法流程如下:

  • 初始化:创建一个空栈 stack,以及一个与输入数组 nums 等长的效果数组 result,初始值全部设置为 -1(体现没有找到更大元素)。
  • 遍历数组

    • 对于数组中的每一个元素 nums

      • 当栈不为空且 nums 大于栈顶元素所对应的数组元素时,弹出栈顶元素,并将 result 数组中对应的位置更新为 nums(由于此时 nums 是栈顶元素的下一个更大元素)。
      • 将当前元素的索引 i 压入栈中。


  • 处置处罚完成

    • 遍历竣事后,栈中剩余的元素体现这些位置上没有比它们更大的元素,效果数组中对应的位置仍然保持为 -1。

算法模板

  1. vector<int> findNextGreaterElement(const vector<int>& nums) {  
  2.     int n = nums.size();  
  3.     vector<int> ans(n, -1); // 初始化结果数组,所有位置都设为-1  
  4.     stack<int> sta; // 用于存储元素的索引  
  5.   
  6.     for (int i = 0; i < n; i++) {  
  7.         // 当栈不为空且当前元素大于栈顶索引对应的元素时  
  8.         while (!sta.empty() && nums[sta.top()] < nums[i]) {  
  9.             ans[sta.top()] = i; // 更新栈顶索引对应的结果  
  10.             sta.pop(); // 弹出栈顶索引  
  11.         }  
  12.         sta.push(i); // 将当前索引压入栈  
  13.     }  
  14.     return ans; // 返回结果数组  
  15. }  
复制代码
例题

P5788 【模板】单调栈
给定一个包罗n个整数的数列a1,a2,…,an。
界说一个函数f(i),该函数体现在数列中第i个元素之后(不包罗第i个元素本身),第一个大于ai的元素的位置索引。假如不存在如许的元素,则f(i)=0。任务是盘算并输出f(1),f(2),…,f(n)的值。
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main(){
  4.     int n;
  5.     cin>>n;
  6.     vector<int> v(n);
  7.     for(int &i:v)cin>>i;
  8.     stack<int> sta;
  9.     vector<int> ans(n,-1);
  10.     for(int i=0;i<n;i++){
  11.         while(not empty(sta) and v[sta.top()]<v[i]){
  12.             ans[sta.top()]=i;
  13.             sta.pop();
  14.         }
  15.         sta.push(i);
  16.     }
  17.     for(int i:ans)cout<<i+1<<' ';
  18. }
复制代码
P1901 发射站
某地有 N 个能量发射站排成一行,每个发射站 i 都有不类似的高度 Hi,并能向双方(两端的发射站只能向一边)同时发射能量值为 Vi 的能量,发出的能量只被双方迩来的且比它高的发射站汲取。显然,每个发射站发来的能量有大概被 0 或 1 或 2 个其他发射站所担当。
请盘算出汲取最多能量的发射站汲取的能量是多少。
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int main(){
  4.     int n;
  5.     cin>>n;
  6.     vector<int> H(n);
  7.     vector<int> val(n);
  8.     for(int i=0;i<n;i++)cin>>H[i]>>val[i];
  9.     vector nextG=[](vector<int> v){
  10.         int n=v.size();
  11.         vector<int> res(n,-1);
  12.         stack<int> sta;
  13.         for(int i=0;i<n;i++){
  14.             while(not empty(sta) and v[sta.top()]<v[i]){
  15.                 res[sta.top()]=i;
  16.                 sta.pop();
  17.             }
  18.             sta.push(i);
  19.         }
  20.         return res;
  21.     }(H);
  22.     vector prevG=[](vector<int> v){
  23.         int n=v.size();
  24.         vector<int> res(n,-1);
  25.         stack<int> sta;
  26.         for(int i=n-1;~i;i--){
  27.             while(not empty(sta) and v[sta.top()]<v[i]){
  28.                 res[sta.top()]=i;
  29.                 sta.pop();
  30.             }
  31.             sta.push(i);
  32.         }
  33.         return res;
  34.     }(H);
  35.     vector<int> ans(n);
  36.     for(int i=0;i<n;i++){
  37.         if(~nextG[i])ans[nextG[i]]+=val[i];
  38.         if(~prevG[i])ans[prevG[i]]+=val[i];
  39.     }
  40.     cout<<*max_element(ans.begin(),ans.end())<<endl;
  41. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表