维护一个单调队列,以最小值为例,队首是最小值的下标,将新加入的元素加入到队尾,但要pop掉那些比新加入元素还要大的元素再加入队尾(即如果比队首最小值还要小将整个队列pop掉再加入队尾),但是队首元素不一定就是这个窗口的答案,它可能在窗口的左边,所以从队首开始pop掉那些下标比i-m还要小的元素,最大值同理;
#include <cstdio> #include <queue> using namespace std; const int N = 1e6+10; int n,m,a[N]; void mi_deque(){ deque<int> q; for(int i = 0;i < n;i++){ while(!q.empty()&&a[q.back()] > a[i]){ q.pop_back(); } q.push_back(i); while(!q.empty()&&q.front() <= i-m){ q.pop_front(); } if(i >= m-1){ printf("%d ",a[q.front()]); } } puts(""); } void mx_deque(){ deque<int> q; for(int i = 0;i < n;i++){ while(!q.empty()&&a[q.back()] < a[i]){ q.pop_back(); } q.push_back(i); while(!q.empty()&&q.front() <= i-m){ q.pop_front(); } if(i >= m-1){ printf("%d ",a[q.front()]); } } puts(""); } int main(){ scanf("%d%d",&n,&m); for(int i = 0;i < n;i++) scanf("%d",a+i); mi_deque(); mx_deque(); return 0; }