單調隊列
單調隊列顧名思義就是具有單調性的隊列,其中單調性可以單調遞增也可以單調遞減,並且。隊首和隊尾可以進行出隊操作,隊尾可以進行入隊操作。隊首元素維護的是區間的最大值或最小值
單調隊列的形象比喻
假如某高校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;
}