一类需要用到单调队列的题目

Posted babydragon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一类需要用到单调队列的题目相关的知识,希望对你有一定的参考价值。

直方图的最大矩形面积

n*m矩阵空地周长

水坑的最大储水量

一维

  1. 给h
  2. 给地面的高和天花板的高
  3. 地面是一个三角形的斜坡

二维

  1. 仅给地面的高
    NYOJ 547
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
typedef long long ll;
ll a[310][310];
bool vis[310][310];
int n, m;
int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };
struct node{
    int x, y, v;
    bool operator < (const node & oth)const
    {
        return v > oth.v;   // 每一层都按从小到大的值排
    }
};
priority_queue<node>pq;
void bfs()
{
    ll ans = 0;
    while (!pq.empty())
    {
        int x = pq.top().x, y = pq.top().y, v = pq.top().v;
        pq.pop();
        if (vis[x][y])
            continue;
        vis[x][y] = 1;
        for (int i = 0; i < 4; i++)
        {
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            int vv = a[xx][yy];
            if (xx < n && xx > 1 && yy < m && yy > 1 && !vis[xx][yy])
            {
                if (vv < v) //若该点小于当前点,则可升高
                {
                    ans += v - vv;
                    a[xx][yy] = v; //更新信息
                }
                pq.push({ xx, yy, a[xx][yy] });
            }       
        }
    }
    cout << ans << endl;
}
int main(){
    while (cin >> m >> n)
    {
        memset(vis, 0, sizeof vis);
        while (!pq.empty())
            pq.pop();
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
            {
                cin >> a[i][j];
                if (i == 1 || j == 1 || i == n || j == m)
                    pq.push({ i, j, a[i][j] }); //先压入边界的点
            }
        bfs();
        /*for (int i = 1; i <= n; i++, cout << endl)
            for (int j = 1; j <= m; j++)
                cout << a[i][j] << " ";*/
    }
    return 0;
}

以上是关于一类需要用到单调队列的题目的主要内容,如果未能解决你的问题,请参考以下文章

单调队列题目练习

单调队列模板

一类基于单调性的题目

单调队列

面试常考算法题(考察单调队列)--滑动窗口的最大值

牛客多校2021 K.King of Range(ST表+单调队列)