【模板】 滑動視窗
阿新 • • 發佈:2020-09-22
傳送門
題意
長度為\(n\)的序列,只能看到長度為\(k\)的滑動視窗,從陣列的最左邊移動到最右邊,求滑動過程中每個滑動視窗的最大值和最小值
資料範圍
\(1\leq n\leq 10^{6}\)
題解
-
單調佇列中存下標,判斷視窗長度,當求視窗中的最小值時,如果佇列中存在兩個元素,滿足 \(a_{i} \geq a_{j}\)且\(i<j\),那麼\(a_{i}\)不會被選為最小值,出隊;
-
此時佇列中剩下的元素嚴格單調遞增,所以隊頭就是整個佇列中的最小值,可以用\(O(1)\)的時間找到;
-
為了維護佇列的這個性質,我們在往隊尾插入元素之前,先將隊尾大於等於當前數的元素全部彈出即可;這樣所有數均只進隊一次,出隊一次,所以時間複雜度是\(O(n)\)
Code
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,k; int a[N]; int que[N],tt,hh=1; int main(){ cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ if(hh<=tt && i-k+1>que[hh]) hh++; while(hh<=tt && a[que[tt]]>=a[i]) tt--; que[++tt]=i; if(i-k+1>0) cout<<a[que[hh]]<<' '; } cout<<endl; hh=1,tt=0; for(int i=1;i<=n;i++){ if(hh<=tt && i-k+1>que[hh]) hh++; while(hh<=tt && a[que[hh]]<=a[i]) tt--; que[++tt]=i; if(i-k+1>0) cout<<a[que[hh]]<<' '; } cout<<endl; }