POJ2823-Sliding Window
阿新 • • 發佈:2018-04-28
IT 區間 for urn pac LG div clu can
給定兩個數n和k,接下來給出n個數的數列。每次維護一個長度為k的窗口,求出這個範圍的最大值和最小值。每次向右移動一個單位。
考慮如何得出一個區間的最大值,每次增加一個數,如果這個數比當前的最大值小,如何是可以不用維護的。如果比當前值大,那麽就要考慮。但是當這個最大值在最左邊的時候,它下一次就不能在這個區間了。所以我們要維護的是一個值可以存在的最左的位置。即位置i的生存期最多是i+k,但如果中間出現比它大的數,那麽就沒必要維護這個數了,可以用出現的數代替它。因為它總是比維護當前的數更優,無論是數值上還是位置上。
也就是說,我們要維護一個遞減的數列,可以用單調隊列實現做到O(n)的復雜度。
最小值同理,代碼如下:
#include <iostream> #include <stdio.h> #include <string.h> #include <queue> #include <algorithm> using namespace std; int n,k,v[2333333],q[23333333]; int main() { while(~scanf("%d%d",&n,&k)){ for(int i=1;i<=n;++i) scanf("%d",&v[i]);int l=1,r=1; q[1]=0; v[0]=1e9; for(int i=1;i<=n+1;++i){ while(l<=r&&q[l]+k<i) ++l; if(i<=k) ; else printf("%d ",v[q[l]]); while(l<=r&&v[q[r]]>=v[i])--r; q[++r]=i; } puts(""); //printf("%d\n",v[q[l]]); l=1,r=1; q[1]=0; v[0]=-1e9; for(int i=1;i<=n+1;++i){ while(l<=r&&q[l]+k<i) ++l; /* for(int j=l;j<=r;++j) printf("%d ",v[q[j]]); puts(""); */ if(i<=k) ; else printf("%d ",v[q[l]]); while(l<=r&&v[q[r]]<=v[i]) --r; q[++r]=i; } puts(""); //printf("%d\n",v[q[l]]); } return 0; }
POJ2823-Sliding Window