洛谷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; }