AcWing 滑動視窗 單調佇列

2021-09-26 08:58:13 字數 1757 閱讀 2914

時/空限制:1s / 64mb

給定乙個大小為n≤106的陣列。

有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。

您只能在視窗中看到k個數字。

每次滑動視窗向右移動乙個位置。

以下是乙個例子:

該陣列為[1 3 -1 -3 5 3 6 7],k為3。

視窗位置

最小值最大值

[1 3 -1] -3 5 3 6 7-13

1 [3 -1 -3] 5 3 6 7-33

1 3 [-1 -3 5] 3 6 7-35

1 3 -1 [-3 5 3] 6 7-35

1 3 -1 -3 [5 3 6] 736

1 3 -1 -3 5 [3 6 7]37

您的任務是確定滑動視窗位於每個位置時,視窗中的最大值和最小值。

輸入包含兩行。

第一行包含兩個整數n和k,分別代表陣列長度和滑動視窗的長度。

第二行有n個整數,代表陣列的具體數值。

同行資料之間用空格隔開。

輸出包含兩個。

第一行輸出,從左至右,每個位置滑動視窗中的最小值。

第二行輸出,從左至右,每個位置滑動視窗中的最大值。

8 3

1 3 -1 -3 5 3 6 7

-1 -3 -3 -3 3 3

3 3 5 5 6 7

題意:給你乙個長度為n的序列,長度為k的視窗在上面向右移動,求出每次移動時視窗內數字的最小值和最大值。

思路:維護兩個佇列,乙個是最小值,乙個是最大值。以最小值為例,最大值同理。

求最小值:建立乙個單調遞增佇列,元素從左到右依次入隊,入隊之前必須從佇列尾部開始刪除那些比當前入隊元素大或者相等的元素,直到遇到乙個比當前入隊元素小的元素,或者隊列為空為止。此時佇列中剩下的元素嚴格單調遞增,所以隊頭就是整個佇列中的最小值,若此時隊頭元素不在視窗中,則從隊頭刪除元素,直到隊頭在視窗中為止。然後把當前元素插入隊尾。

accepted code:

/* 

* @author: lzyws739307453

* @language: c++

*/#include using namespace std;

const int maxn = 1000005;

struct queue

void push(int x)

void pop_front()

void pop_back()

int front()

int back()

int size()

bool empty()

}qmin, qmax;

int cnt_max = 0, cnt_min = 0;

int spt[maxn], res_max[maxn], res_min[maxn];

int main()

for (int i = m; i <= n; i++)

printf("%d%c", spt[res_min[i]], "\n "[i != n]);

for (int i = m; i <= n; i++)

printf("%d%c", spt[res_max[i]], "\n "[i != n]);

return 0;

}

單調佇列 ACwing滑動視窗

acwing 滑動視窗 單調對列好久之前就學了,但是一直沒有深刻理解,這次又學了一下,感覺理解了點,就寫篇部落格記錄一下。滑動視窗這題是個經典的題,可以用線段樹寫,但 量有點大,而且使用空間比較大,如果卡空間的話,顯然線段樹是過不去的,rmq在洛谷上好像是不能寫,倍增的思想可以水過時間,但這題卻過不...

Acwing 154 滑動視窗 單調佇列

這題和poj2823是一樣的 解析 暴力,直接對於每k個都遍歷一遍,很顯然複雜度o nk 的話行不通。對於這類問題,有乙個比較一致的思路,就是有些數字是無用的,或者用了幾次後就要被扔掉的,後續根本就排不上用場。比如有ai,aj,ax,ax ai aj,找ax左邊第乙個比它小的數,很明顯,ai壓根不需...

單調佇列 滑動視窗

nkoj 2152 description 給你乙個長度為n n 10 6 的陣列,乙個長為k的滑動的窗體從最左移至最右端,你只能見到視窗的k個數,每次窗體向右移動一位,找出窗體所包含的數字的最大和最小值,如下表所示 k的值為3 視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 ...