1. 程式人生 > WINDOWS開發 >B - Sliding Window 單調佇列

B - Sliding Window 單調佇列

題意

  給你一串長為n的序列,給你一個整數k代表視窗的長度為k,從序列左端到右端,你需要找到每個連續的長度為k的區間的最小值和最大值

思路

  如果暴力來做,遍歷n次k個數,那就是n方的複雜度;如果維護一個線段樹那就是nlogn,每個數只被插入一次和刪除一次。

  我們可以維護兩個單調佇列,單調遞增佇列用於計算視窗的最小值,每刪去一個數就看隊頭有沒有出去,出去就出隊,新增一個數就和隊尾比較,直到能放下去,維護n次,每次的隊頭就是區間的最小值,最大值同理,複雜度為n。

AC程式碼

#include<iostream>
#include<stdio.h>
using namespace
std; const int maxn=1e6+5; int a[maxn],que[maxn],label[maxn]; int n,k,head,tail; int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); head=1;tail=0; for(int i=1;i<=n;i++){ while(head<=tail&&i-label[head]>=k) head++;
while(head<=tail&&que[tail]>=a[i]) tail--; que[++tail]=a[i]; label[tail]=i; if(i>=k) printf("%d ",que[head]); } printf("\n"); head=1;tail=0; for(int i=1;i<=n;i++){ while(head<=tail&&i-label[head]>=k) head++;
while(head<=tail&&que[tail]<=a[i]) tail--; que[++tail]=a[i]; label[tail]=i; if(i>=k) printf("%d ",que[head]); } return 0; }