滑动窗口思想 && 滑动窗口求最大最小值 洛谷1886

滑动窗口:
一个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 ;
}   

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/81322241