单调队列--滑动区间最值

问题

题目描述

已知一个数组,a[1]~a[n]共n项,问1~k, 2~(k+1), 3~(k+2)……(n-k+1)~n这些区间的最大值分别是多少?

输入:

第1行2个数,n和k,含义如题中所述。(1<=k<=n<=100000)

接下来1行,有n个数,表示a数组。(a[i]<=1000000)

输出:

1行,共(n-k+1)个数,表示每个区间的最大值。

样例:

输入:
8 3
5 9 4 2 6 10 4 1
输出:
9 9 6 10 10 10



数组模拟实现
#include <bits/stdc++.h>
using namespace std;
int n, k, a[100005];
int q[100005];//q存a数组的下标
int main(){
    cin >> n >> k;
    for(int i=1;i<=n;i++){
        cin >> a[i];//输入
    }
    int l=1,r=1;
    for(int i=1;i<=n;i++){
        while(i-k>=q[l]&&l<r)l++;//队首元素不在当前k区间内了
        while(l<r&&a[q[r-1]]<a[i])r--;//如果队尾元素小于当前值,则队尾元素不再可能是最大值
        q[r++]=i;//加入第i个数
        if(i>=k)
            cout<<a[q[l]]<<' ';
    }
}

stl双端队列

#include <bits/stdc++.h>
using namespace std;
int n, k, a[100005];
deque<int> q;
int main(){
    cin >> n >> k;
    for(int i=1;i<=n;i++){
        cin >> a[i];//输入
    }
    for(int i=1;i<=n;i++){
        while(!q.empty()&&i-k>=q.front())q.pop_front();//队首元素不在当前k区间内了
        while(!q.empty()&&a[i]>a[q.back()])q.pop_back();//如果队尾元素小于当前值,则队尾元素不再可能是最大值
        q.push_back(i);//加入第i个数
        if(i>=k)
            cout<<a[q.front()]<<' ';
    }
}
原文地址:https://www.cnblogs.com/xuanzo/p/14507338.html