单调队列(滑动窗口)模板

题目

单调队列(滑动窗口)模板

时间复杂度:\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,k,a[N],ans1[N],ans2[N];
int q[N],hd,tl;//q[N]存的是位置
void calc(int ans[]){
	hd=1,tl=0;//清空
	for(int i=1;i<=n;i++){//枚举窗口右端
		while(hd<=tl&&i-q[hd]+1>k) q[hd++]=0;//弹出队首已经离开窗口的元素
		while(hd<=tl&&a[q[tl]]>a[i]) q[tl--]=0;//从队尾踢掉之前所有比当前元素大的数
		q[++tl]=i;//将当前元素位置加入队尾
		if(i>=k) ans[i-k+1]=q[hd];//队头即为最小值
	}
	return ;
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	calc(ans1);//计算滑动窗口最小值位置,答案计入ans1
	for(int i=1;i<=n-k+1;i++){
		cout<<a[ans1[i]]<<' ';
	}
	cout<<'\n';
	for(int i=1;i<=n;i++){
		a[i]=-a[i];//取相反数
	}
	calc(ans2);//计算滑动窗口最大值位置(此时依旧求的是最小值位置),答案计入ans2
	for(int i=1;i<=n-k+1;i++){
		cout<<-a[ans2[i]]<<' ';//因为求最大值,所以再取相反数
	}
	return 0;
}
posted @ 2026-08-08 11:44  decentz  阅读(5)  评论(0)    收藏  举报