洛谷P1886 滑动窗口 /【模板】单调队列 /Poj 2823 Sliding Windows

【题目】

这里

 

【审题】

略。

 

【分析】

1.问:暴力怎么写?

  答:枚举区间起点,直接模拟。时间复杂度O(nk).

2.问:为什么用单调队列更优?

  答:(1)单调队列中的元素或相关数据具有单调性,可用于求最值。

    (2)单调队列中的元素下标一定递增,符合窗口滑动的特点。

3.问:还可以用什么来实现?

  答:线段树、st表(都为nlogn),但数据范围1e6,必定会卡。

 

【做题时遇到的问题】

 如图,第一种写法没有先判重就调用了q.back(),导致RE。

在csp-s 2021 的时候想到过这个问题,但是没有今天这么透彻。当时的做法是如果优先队列为空,则单独设一个值为0的变量来比较。

 

【代码实现】

#include<bits/stdc++.h>
using namespace std;
deque<int> q;
int n,m,a[1000005];
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        
        // while(a[i]<a[q.back()]&&!q.empty()){
        //     q.pop_back();
        // }
        while(!q.empty()&&a[i]<a[q.back()]) q.pop_back();


        
        q.push_back(i);
        if(i>=m)
        {
            while(i-q.front()>=m&&!q.empty())
            {
                q.pop_front();
            }
            printf("%d ",a[q.front()]);
        }
    }
    printf("\n");
    while(!q.empty()) q.pop_front();
    for(int i=1;i<=n;i++){
        while(!q.empty()&&a[i]>a[q.back()]) q.pop_back();
        q.push_back(i);
        if(i>=m)
        {
            while(i-q.front()>=m&&!q.empty())
            {
                q.pop_front();
            }
            printf("%d ",a[q.front()]);
        }
    }
    return 0;
}

 

posted @ 2021-11-10 22:03  TheZealous  阅读(34)  评论(0编辑  收藏  举报