定义
队列中的元素始终保持着单增或者单减的特性。
类似于单调栈
但是不同于单调栈,队列我们可以获取队列中数据的个数
注意是双端队列
于是我们就可以解决类似于“滑动窗口”的问题,区间最小值
示例看上一篇单调栈的
代码
deque<int> q; k为区间长度
while(!q.empty()&&q.back()>=x) q.pop_back();//这里是严格递增求区间最小值,改成<=求最大
q.push_back(##code##);
if(i-q.front()+1>k) q.pop_front();
if(i>=k){//当满足区间长度时
//##code##
}
题目
1,滑动窗口

输入描述
输入由两行组成。第一行包含两个整数n和k,它们分别是数组和滑动窗口的长度。第二行有n 个整数。
输出描述
输出中有两行。第一行分别给出了窗口中每个位置的最小值,从左到右。第二行给出最大值。
输入样例
8 3 1 3 -1 -3 5 3 6 7
输出样例
-1 -3 -3 -3 3 3
3 3 5 5 6 7

AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
deque<int> q;
int k,n,a[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
int x=a[i];
while(!q.empty()&&a[q.back()]>x) q.pop_back();
q.push_back(i);
if(i-q.front()+1>k) q.pop_front();
if(i>=k){
cout<<a[q.front()]<<" ";
}
}
cout<<endl;
q.clear();
for(int i=1;i<=n;i++){
int x=a[i];
while(!q.empty()&&a[q.back()]<x) q.pop_back();
q.push_back(i);
if(i-q.front()+1>k) q.pop_front();
if(i>=k){
cout<<a[q.front()]<<" ";
}
}
return 0;
}
理想正方形:

输出描述
仅一行一个整数,即小 Z 能够得到的最大幸运值。
输入样例
6 3
1 -2 3 -4 5 -6
输出样例
5
最 初省的一个题,因为是矩形,所以需要先一行一行处理区间最小值,然后再用同样方法处理列,思路简单但是不好写
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1005;
deque<int> Max,Min;
int k,n,m,ans=0x3f3f3f3f3f,a[N][N],r_max[N][N],r_min[N][N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
while(!Max.empty()&&a[i][Max.back()]<=a[i][j]) Max.pop_back();
Max.push_back(j);
if(j-Max.front()+1>k)
Max.pop_front();
while(!Min.empty()&&a[i][Min.back()]>=a[i][j]) Min.pop_back();
Min.push_back(j);
if(j-Min.front()+1>k)
Min.pop_front();
if(j>=k){
r_min[i][j]=a[i][Min.front()];
r_max[i][j]=a[i][Max.front()];//行的区间最小值
}
}
Max.clear();Min.clear();
}//先处理行
for(int j=k;j<=m;j++){
for(int i=1;i<=n;i++){
while(!Max.empty()&&r_max[Max.back()][j]<=r_max[i][j]) Max.pop_back();
Max.push_back(i);
if(i-Max.front()+1>k)
Max.pop_front();
while(!Min.empty()&&r_min[Min.back()][j]>=r_min[i][j]) Min.pop_back();
Min.push_back(i);
if(i-Min.front()+1>k)
Min.pop_front();
if(i>=k){
ans=min(ans,r_max[Max.front()][j]-r_min[Min.front()][j]);//统计答案
}
}
Max.clear();Min.clear();
}在处理列
cout<<ans;
return 0;
}
1823

被折叠的 条评论
为什么被折叠?



