單調隊列和單調棧(通俗易懂)

單調隊列

單調隊列顧名思義就是具有單調性的隊列,其中單調性可以單調遞增也可以單調遞減,並且。隊首和隊尾可以進行出隊操作,隊尾可以進行入隊操作。隊首元素維護的是區間的最大值或最小值

單調隊列的形象比喻

假如某高校ACM校隊每年只有一個名額去參加比賽,所以只能選出能力最強的人去參加,因爲該校只有大三及其以下能夠參加該比賽,所以超過該限制的人將會被淘汰。現該隊有三名隊員分別是張三(年級:大三,能力:9)李四(年級:大二,能力:8)王五(年級:大一,能力:6)。在這一年,因爲張三能力最強所以只有張三能夠參加比賽。過了一年後,張三退役(也就是隊首出隊的操作),現在隊裏成員信息是李四(年級:大三,能力:8)王五(年級:大二,能力:6)兩人,這時候來了一個小萌新(隊尾入隊),他的信息是劉六(年級:大一,能力:10)。因爲劉六的能力比李四王五強,所以在接下來不加新人的情況下,一直會是劉六參加比賽,李四王五的大學生涯不會參見比賽了(李四王五隊尾出隊)。

滑動窗口

題目描述
​ 給出一個長度爲 𝑁 的數組,一個長爲 𝐾 的滑動窗口從最左移動到最右,每次窗口移動,如下圖:
在這裏插入圖片描述
找出窗口在各個位置時的極大值和極小值。

輸入
​ 第一行兩個數 𝑁,𝐾。
​ 第二行有 𝑁 個數,表示數組中的元素。

輸出
​ 輸出兩行,第一行爲窗口在各個位置時的極小值,第二行爲窗口在各個位置時的極大值。

樣例輸入
8 3
1 3 -1 -3 5 3 6 7

樣例輸出
-1 -3 -3 -3 3 3
3 3 5 5 6 7

數據規模與約定
​ 時間限制:1 s
​ 內存限制:256 M
​ 100% 的數據保證 1≤𝑁≤300000

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define MAX_N 300000
int a[MAX_N + 5];
int q[MAX_N + 5], head = 0, tail = 0;

int main() {
    int n, k;
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) {
        while (tail - head && a[q[tail - 1]] >= a[i]) tail--;  //隊尾出隊
        q[tail++] = i;                            //隊尾入隊
        if (q[head] <= i - k) head++;  //隊首入隊
        if (i < k) continue;
        i == k || cout << " ";
        cout << a[q[head]];
    }
    cout << endl;
    head = tail = 0;
    for (int i = 1; i <= n; i++) {
        while (tail - head && a[q[tail - 1]] <= a[i]) tail--;
        q[tail++] = i;
        if (q[head] <= i - k) head++;
        if (i < k) continue;
        i == k || cout << " ";
        cout << a[q[head]];
    }
    cout << endl;
    return 0;
}

單調棧

單調棧與單調隊列性質類似通俗的說就是具有單調性的棧,其中單調性可以單調遞增也可以單調遞減,並且,隊尾可以進行出隊操作,隊尾可以進行入隊操作。
單調隊列:擅長維護區間最大/最小值,最小值對應着遞增隊列,最大值對應着遞減隊列
單調棧::擅長維護最近大於/小於關係,從左側先入棧就是維護左側最近關係,從右側先入棧就是維護右側最近關係
最大矩形面積

題目描述
​ 給定從左到右多個矩形,已知這此矩形的寬度都爲 1,長度不完全相等。這些矩形相連排成一排,求在這些矩形包括的範圍內能得到的面積最大的矩形,打印出該面積。所求矩形可以橫跨多個矩形,但不能超出原有矩形所確定的範圍。
在這裏插入圖片描述

輸入
​ 輸入共一行,第一個數表示矩形的個數 𝑁。接下來 𝑁 個數表示矩形的大小。(1≤𝑁≤100000)

輸出
​ 輸出最大矩形面積。

樣例輸入
7
2 1 4 5 1 3 3

樣例輸出
8

數據規模與約定
​ 時間限制:1 s
​ 內存限制:256 M
​ 100% 的數據保證 1≤𝑁≤100000

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define MAX_N 100000
long long a[MAX_N + 5];
long long s[MAX_N + 5], top = -1;
long long l[MAX_N + 5], r[MAX_N + 5];

int main() {
    long long n;
    cin >> n;
    for (long long i = 1; i <= n; i++) cin >> a[i];
    a[0] = a[n + 1] = -1;
    s[top = 0] = 0;
    for (long long i = 1; i <= n; i++) {
        while (a[s[top]] >= a[i]) --top;
        l[i] = s[top];
        s[++top] = i;
    }
    s[top = 0] = n + 1;
    for (long long i = n; i >= 1; i--) {
        while (a[s[top]] >= a[i]) --top;
        r[i] = s[top];
        s[++top] = i;
    }
    long long ans = 0;
    for (long long i = 1; i <= n; i++) {
        ans = max(ans, a[i] * (r[i] - l[i] - 1));
    }
    cout << ans << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章