单调队列

 

 

 重点:将队列中没有用的元素删除。

如果在窗口中存在i<j,ai>aj,那么在窗口向右移动的过程中,只要aj存在,那么ai就永远不可能成为最小值。应该被移除。

因此,当窗口移动到aj的那一刻,ai以及窗口中一切大于或者等于aj的元素都应该被移出队列。形成一个单调递增的队列,找队首就是最小值。找最大值的话反过来就行。

 #include<iostream>

#include<queue>

using namespace std;

const int N=1e6+10;

int hh,tt=-1;//队列要定义队头和队尾

int n,k;

int a[N];

int q[N];//队列

int main(){

cin>>n>>k;

for(int i=0;i<n;i++){

cin>>a[i];

}

//最小值

for(int i=0;i<n;i++){

if(hh<=tt && q[hh]<i-k+1) hh++;//队头超出窗口,出队列

while(hh<=tt && a[q[hh]]>=a[i]) tt--;//如果窗口中的值大于即将进队列的元素,则删去。直到删到窗口中的值小于即将进队列的那个元素为止,形成一个单调递增的队列。

q[++tt]=i;//即将进队列的那个值进队列

if(i>=k-1) cout<<a[q[hh]]<<' ';//保证窗口中有k的数字时,开始输出队头(是最小值)。(i-1>=k)

puts("");//空格

hh=0,tt=-1;//重新给队头和队尾赋值

//开始求最大值 就是判断如果进队列的那个值大于队尾的值,则删除队尾,直到形成一个单调递减的队列。然后输出队头就是最大值。

for(int i=0;i<n;i++){

if(hh<=tt && q[hh]<i-k+1) hh++;

while(hh<=tt && a[q[hh]]>=a[i]) tt--;

q[++tt]=i;

if(i>=k-1) cout<<a[q[hh]]<<' ';

}

return 0;

}

 

posted @ 2023-03-13 22:48  chenxinyue  阅读(11)  评论(0编辑  收藏  举报