1. 程式人生 > 其它 >專題學習1 - I - 滑動視窗

專題學習1 - I - 滑動視窗

題意

給一個長度為 N 的陣列,一個長為 K 的滑動窗體從最左端移至最右端,你只能看到視窗中的 K 個數,每次窗體向右移動一位,如下圖:

視窗位置 最小值 最大值
[1 3 -1] -3 5 3 6 7 −1 3
1 [3 -1 -3] 5 3 6 7 −3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7

你的任務是找出窗體在各個位置時的最大值和最小值。

輸入格式

第 1 行:兩個整數 NK
第 2 行:N

個整數,表示陣列的 N 個元素(≤2×10^9);

輸出格式

第一行為滑動視窗從左向右移動到每個位置時的最小值,每個數之間用一個空格分開;
第二行為滑動視窗從左向右移動到每個位置時的最大值,每個數之間用一個空格分開。

思路

單項佇列模板題。

程式碼

#include <iostream>
using namespace std;
const int N = 5 + 1e6;

int a[N];
int q1[N], q2[N];

int main() {
    int n, m, hh, tt;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);

    //min_deque
    hh = 1, tt = 0;
    for (int i = 1; i <= n; i++) {
        while (hh <= tt && q1[hh] + m <= i) hh++;
        while (hh <= tt && a[i] < a[q1[tt]]) tt--;
        q1[++tt] = i;
        if (i >= m) printf("%d ", a[q1[hh]]);
    }
    cout << '\n';

    //max_deque
    hh = 1, tt = 0;
    for (int i = 1; i <= n; i++) {
        while (hh <= tt && q2[hh] + m <= i) hh++;
        while (hh <= tt && a[i] > a[q2[tt]]) tt--;
        q2[++tt] = i;
        if (i >= m) printf("%d ", a[q2[hh]]);
    }
    cout << '\n';

    return 0;
}