题目描述
一个含有 n 项的数列,求出每一项前的 m 个数到它这个区间内的最小值。若前面的数不足 m 项则从第 1 个数开始,若前面没有数则输出 0。
输入格式
第一行两个整数,分别表示 n,m。
第二行,n 个正整数,为所给定的数列 ai。
输出格式
n 行,每行一个整数,第 i 个数为序列中 ai 之前 m 个数的最小值。
输入输出样例
输入 #1
6 2 7 8 1 4 3 2
输出 #1
0 7 7 1 1 3
单调队列
单调队列是一种主要用于解决滑动窗口类问题的数据结构,即,在长度为 m 的序列中,求每个长度为 n 的区间的区间最值。它的时间复杂度是 O(n) ,在这个问题中比 O(nlogn) 的ST表和线段树要优。
单调队列的基本思想是,维护一个双向队列(deque),遍历序列,仅当一个元素可能成为某个区间最值时才保留它。
队列分支
队列题集整合
题意分析
这道题是一道单调队列的模板题,让我们来尝试一下吧!
解题思路
发现是求队列最小值,那么就要判断是否是单调递减,肝了一会,代码就写出来啦!(不要忘记了换行)
#include<bits/stdc++.h>
using namespace std;
long long a,b,c[2000005];
deque<int >q;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>a>>b;
for(int i=1;i<=a;i++){
cin>>c[i];
}
cout<<0<<endl;
for(int i=1;i<a;i++){
while(!q.empty()&&c[q.back()]>c[i]){
q.pop_back();
}
q.push_back(i);
while(!q.empty()&&q.front()<(i-b+1)){
q.pop_front();
}
cout<<c[q.front()]<<endl;
}
return 0;
}
但是不知道为什么,结果总会TLE,并且加了快读也不管用。
后来想起一件事,换行endl会浪费很多的时间,要用"\n" 降低时间复杂度。
那就再交一遍。
这就AC了,千万别忘记输出用"\n"!
将代码呈现给大家:
#include<bits/stdc++.h>
using namespace std;
long long a,b,c[2000005];
deque<int >q;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>a>>b;
cout<<0<<endl;
for(int i=1;i<=a;i++){
cin>>c[i];
if(i==a){
continue;
}
while(!q.empty()&&c[q.back()]>c[i]){
q.pop_back();
}
q.push_back(i);
if(!q.empty()&&q.front()<(i-b+1)){
q.pop_front();
}
cout<<c[q.front()]<<"\n";
}
return 0;
}
点赞收藏不迷路,如果还有更好的方法可以提出来欧!