维护一个队头和队尾
单调队列的性质 单调
时间 n
这边讲维护小的
因为维护单调 从队尾进去 经过
w 1 3 -1 -3 3 3 6 7
ind 1 2 3 4 5 6 7 8 k=3
初始话一下
头 w 1 尾
ind 1
w 1 3 因为3比1 大 放在后面
ind 1 2
w 1 3 然后要加入-1 比较 比前面2个都小 所以 -1
ind 1 2 3
初始化也就完成了
接下来其实每个入队就和初始化差不多 判断是否比当前的大 大的话 pop 最后放进去
然后因为每次队头都是最小的 那么只要这个合法就行了 如果这个下标不在 那个k内 就去掉
最大的同理
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 2000010 #define inf 2000000007 #define mod 1000000007 int z[MAXN]; struct { int w,ind; }q[MAXN]; int mx[MAXN]; int mi[MAXN]; int main() { int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&z[i]); int sz=1; int fr=1; q[1].w=z[1]; q[1].ind=1; for(int i=2;i<k;i++) { while(sz>=fr&&q[sz].w>z[i]) sz--; sz++; q[sz].w=z[i]; q[sz].ind=i; } for(int i=k;i<=n;i++) { while(sz>=fr&&q[sz].w>z[i]) sz--; sz++; q[sz].w=z[i]; q[sz].ind=i; while(q[fr].ind<i-k+1) fr++; mi[i-k+1]=q[fr].w; } for(int i=1;i<n-k+1;i++) printf("%d ",mi[i]); printf("%d ",mi[n-k+1]); fr=1; sz=1; q[1].w=z[1]; q[1].ind=1; for(int i=2;i<k;i++) { while(sz>=fr&&q[sz].w<z[i]) sz--; sz++; q[sz].w=z[i]; q[sz].ind=i; } for(int i=k;i<=n;i++) { while(sz>=fr&&q[sz].w<z[i]) sz--; sz++; q[sz].w=z[i]; q[sz].ind=i; while(q[fr].ind<i-k+1) fr++; mx[i-k+1]=q[fr].w; } for(int i=1;i<n-k+1;i++) printf("%d ",mx[i]); printf("%d ",mx[n-k+1]); return 0; }