洛谷 P1886 滑動視窗 (單調佇列)
阿新 • • 發佈:2020-08-07
題目
有一個長為 nn 的序列 aa,以及一個大小為 kk 的視窗。現在這個從左邊開始向右滑動,每次滑動一個單位,求出每次滑動後窗口中的最大值和最小值。
思路
維護一個單調佇列即可。
程式碼實現
#include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i) #define per(i,n,a) for (int i=n;i>=a;i--) #define MT(x,i) memset(x,i,sizeof(x) ) #define rev(i,start,end) for (int i=0;i<end;i++) #define inf 0x3f3f3f3f #define mp(x,y) make_pair(x,y) #define lowbit(x) (x&-x) #define MOD 1000000007 #define exp 1e-8 #define N 1000005 #define fi first #define se second #define pb push_back typedef long long ll; typedef pair<int ,int> PII; ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; } inline int read() { char ch=getchar(); int x=0, f=1; while(ch<'0'||ch>'9') { if(ch=='-') f = -1; ch=getchar(); } while('0'<=ch&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct node { static const int maxn=1000001; int n,k,a[maxn]; int p[maxn],q[maxn]; int head,tail; void rea () { scanf ("%d %d",&n,&k); rep (i,1,n) scanf ("%d",&a[i]); } void queue_max () { head=1; tail=0; rep (i,1,n) { while (head<=tail&&q[tail]<=a[i]) tail--; q[++tail]=a[i]; p[tail]=i; while (p[head]<=i-k) head++; if (i>=k) printf ("%d ",q[head]); } cout<<endl; } void queue_min () { head=1; tail=0; rep (i,1,n) { while (head<=tail&&q[tail]>=a[i]) tail--; q[++tail]=a[i]; p[tail]=i; while (p[head]<=i-k) head++; if (i>=k) printf ("%d ",q[head]); } printf ("\n"); } }solve; int main () { // freopen ("data.in","r",stdin); solve.rea (); solve.queue_min(); solve.queue_max (); // fclose (stdin); return 0; }