滑动窗口:
一个n个数的序列,要求所有的连续k个数的最大值 或者 最小值,都可以用这种方法实现。
以求最大值为例(最小值反着来就可以了)
窗口大小为k,遍历数组,每次a[i]和队列尾部的元素比较,清空小于a[i]的所有元素,小于的话直接加入。
这样维护是因为窗口不断向后滑动,前面的小于a[i]的一定不会成为后面窗口的最大值,而后面小于它的 等待 大于窗口值时 队头(最大元素)出队,有可能成为最大值。
题目链接
思路:双端队列实现。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int AX = 2e6+66;
LL a[AX];
LL deq_MAX[AX];
LL deq_MIN[AX];
//deque<int>deq;
int main(){
int n , k ;
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> k ;
for( int i = 1 ; i <= n ; i++ ){
cin >> a[i];
}
int h1 = 1 , t1 = 0 ;
int h2 = 1 , t2 = 0 ;
std::vector<int> v_max;
std::vector<int> v_min;
for( int i = 1 ; i <= n ; i ++ ){
while( h1 <= t1 && a[i] >= a[deq_MAX[t1]] ) t1 -- ;
deq_MAX[++t1] = i ;
while( h2 <= t2 && a[i] <= a[deq_MIN[t2]] ) t2 -- ;
deq_MIN[++t2] = i ;
if( i >= k ){
v_max.push_back(a[deq_MAX[h1]]);
v_min.push_back(a[deq_MIN[h2]]);
while( h1 <= t1 && i - k + 1 >= deq_MAX[h1] ) h1 ++;
while( h2 <= t2 && i - k + 1 >= deq_MIN[h2] ) h2 ++;
}
}
for( int i = 0 ; i < v_min.size() ; i++ ){
cout << v_min[i] << ' ';
}cout << endl;
for( int i = 0 ; i < v_max.size() ; i++ ){
cout << v_max[i] << ' ';
}cout << endl;
return 0 ;
}