当前位置: 首页 > article >正文

单调队列与栈

一.题

1.

思路: 构建小压大的单调递减栈,对于每个栈的元素都进行处理并加到结果上

class Solution {
public:
    int sumSubarrayMins(vector<int>& arr) {
        int stk[10000000],top = 0;
        long long ans = 0;
        
        for(int i =0;i<arr.size();i++){
            while(top&&arr[i]<arr[stk[top-1]]){
                int cur = stk[--top];
                int l = top==0?-1:stk[top-1];
                ans = (ans+(long long)(cur-l)*(i-cur)*arr[cur])%(1000000007);
            }
            stk[top++] = i;
        }
        while(top){
            int cur = stk[--top];
            int l = top==0?-1:stk[top-1];
            ans = (ans+(long long)(cur-l)*(arr.size()-cur)*arr[cur])%(1000000007);
        }
        return ans;
    }
};

 2.

思路: 以每排都为一次底,然后压缩和第一题类似

#include <vector>
#include <string>
#include <algorithm>
#include <climits>

using namespace std;

class Solution {
public:
    int maximalRectangle(vector<string>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return 0;

        int rows = matrix.size();
        int cols = matrix[0].size();
        vector<int> height(cols, 0); 
        int ans = 0; 

        for (int i = 0; i < rows; i++) {
       
            for (int j = 0; j < cols; j++) {
                if (matrix[i][j] == '1') height[j] += 1;  
                else height[j] = 0; 
            }

            int stk[cols + 2], top = 0;
            stk[top++] = -1; 

            for (int j = 0; j <= cols; j++) {
                while (top > 1 && (j == cols || height[stk[top - 1]] >= height[j])) {
                    int curHeight = height[stk[--top]]; 
                    int width = j - stk[top - 1] - 1; 
                    int area = curHeight * width; 
                    ans = max(ans, area); 
                }
                stk[top++] = j; 
            }
        }

        return ans;
    }
};

3.

思路:用单调栈收集每个可能是低点的位置,使得栈严格小压大,单调递增,然后方向遍历全部的元素与栈中元素比较来找距离最远的坡

class Solution {
public:
    int maxWidthRamp(vector<int>& nums) {
        
        int stk[50050],top = 0;
        int ans = 0;
        stk[top++] = 0;

        for(int i =0;i<nums.size();i++){
           if(nums[i]<nums[stk[top-1]])stk[top++] = i;
        }

        for(int i = nums.size()-1;i>=0;i--){
            while(top&&nums[i]>=nums[stk[top-1]]){
                int cur = stk[--top];
                int temp_l = i - cur;
                ans = max(ans,temp_l);
            }
        }
        return ans;
    }
};

4.

思路:还是利用单调栈的特性,大压小,开头从栈底部开始,同时用一个数组标记是不是在栈中

#include <string>
#include <vector>

using namespace std;

class Solution {
public:
    string removeDuplicateLetters(string s) {
        int counts[26] = {0}; 
        bool inStack[26] = {false}; 
        char stk[10005];
        int top = 0; 

        for (char ch : s) 
            counts[ch - 'a']++;

        for (char ch : s) {
            if (inStack[ch - 'a']) {
                counts[ch - 'a']--;
                continue;
            }
            while (top > 0 && stk[top - 1] > ch && counts[stk[top - 1] - 'a'] > 0) {
                inStack[stk[top - 1] - 'a'] = false; 
                top--; 
            }

            stk[top++] = ch;
            inStack[ch - 'a'] = true; 
            counts[ch - 'a']--; 
        }

        string result;
        for (int i = 0; i < top; i++) result += stk[i];
        return result;
    }
};

 5.

思路:因为,鱼是吃右边的更小的鱼,所以方向遍历后往前,因为小不能吃大,为小压大,在用个cnt数组统计每条鱼进行的场数,用max来求最大值

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

int main() {
   int n,ans = -1;
   cin>>n;

   vector<int> fish(n);
   for(int i = 0; i < n; i++)cin>>fish[i];

   vector<int> cnt(n,0);
   stack<int> stk;

   for(int i = n-1; i >= 0; i--){
       while(!stk.empty() && fish[i]>fish[stk.top()]){
           int cur = stk.top();stk.pop();
           cnt[i] = max(cnt[i]+1,cnt[cur]);  
        }
        stk.push(i);
        ans = max(ans,cnt[i]);
   }
   
   cout<<ans;
   return 0;
}

 6.算法竞赛进阶指南

思路:模拟过程即可

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include<queue>

using namespace std;

int main() {
    int cnt[14];
    int time[14];
    vector<vector<char>>tt(14, vector<char>(5, 0));

    for (int i = 1; i <= 13; i++){
        cnt[i] = 4; time[i] = 0;
        for (int j = 1; j <= 4; j++)
            cin >> tt[i][j];
    }
    cnt[13] = 1;
        
    while (cnt[13] <= 4) {
        char temp = tt[13][cnt[13]++];
        if (temp == 'K') continue;

        while (temp != 'K') {
            int num = 0;
            if (temp == 'A')num = 1;
            else if (temp == '0')num = 10;
            else if (temp == 'J')num = 11;
            else if (temp == 'Q')num = 12;
            else num = temp - '0';
   
            time[num]++;
            if (cnt[num] == 0)break;
            temp = tt[num][cnt[num]--];
        }
    }

    int ans = 0;
    for (int i = 1; i <= 12; i++) {
        if (time[i] == 4)ans++;
    }
    cout << ans;
    return 0;
}

 


http://www.kler.cn/a/546079.html

相关文章:

  • 分享一些处理复杂HTML结构的经验
  • 闭源大语言模型的怎么增强:提示工程 检索增强生成 智能体
  • 如何在 ONLYOFFICE 编辑器中使用 DeepSeek
  • python class详解
  • 51单片机09 DS1302时钟
  • HTN77A0F:拥有强制脉宽调制的0.7A同步降压降压变换器资料参数
  • 2025最新深度学习pytorch完整配置:conda/jupyter/vscode
  • 解决DeepSeek服务器繁忙问题
  • Sentinel 持久化配置
  • 『大模型笔记』怎样让Ollama启动的大模型常驻内存(显存)?
  • MySQL-SQL
  • 记录阿里云CDN配置
  • 在1panel中安装 crmeb pro 的简单说明
  • Linux线程概念与线程操作
  • 用deepseek生成图片的一点心得
  • 【做一个微信小程序】校园事件页面实现
  • 【matlab】大小键盘对应的Kbname
  • C#中的Interface、Abstract和Virtual
  • 【删除tomcat默认管理控制台】
  • 深入解析操作系统控制台:阿里云Alibaba Cloud Linux(Alinux)的运维利器