本题是一个滑动窗口问题,在移动过程中改变的是第一个数被丢掉和下一个数加进来。那么可以建立一个队列,如果当前进来的这个数比前面的某些数要大的话就需要出队,因为由于这个更大的数的存在前面的数就不可能变成最大的数。那么就需要直接从队列里面删除。如果第一个在窗口移动的时候被丢掉了同样也要删除。如果新加进来的比队列里面的数要小,那么他就还有称为最大值的潜力,将他放在队尾保留。求最小值同样也是这样。
要注意:由于在窗口移动过程中丢掉的不能直接使用数值是否相等来判断,因为可能有一样的数字造成错误的删除。保存下标才是明智之举。
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6+10; int a[maxn]; int n, k; deque<int> max_dq; deque<int> min_dq; void print_min() { for (int i=1;i<=n;i++) { //如果当前的数比队列里面第一个要大,那么直接将队列全部弹出 while (!max_dq.empty() && a[i]>=a[max_dq.back()]) { max_dq.pop_back(); } max_dq.push_back(i); if (!max_dq.empty() && i-max_dq.front()+1>k) { max_dq.pop_front(); } if (i>=k) printf("%d ", a[max_dq.front()]); } } void print_max() { for (int i=1;i<=n;i++) { //如果当前的数比队列里面第一个要大,那么直接将队列全部弹出 while (!min_dq.empty() && a[i]<=a[min_dq.back()]) { min_dq.pop_back(); } min_dq.push_back(i); if (!min_dq.empty() && i-min_dq.front()+1>k) { min_dq.pop_front(); } if (i>=k) printf("%d ", a[min_dq.front()]); } } int main() { cin>>n>>k; for (int i=1;i<=n;i++) { cin>>a[i]; } print_max(); cout<<endl; print_min(); return 0; }