单调队列


单调就是指一直增或一直减,例如1,2,3,4就是单调增,4,3,2,1就是单调减。而单调队列就有这种性质。

数据结构队列是先进先出,相当于数列3,7,5,9,现在有一个数2要进队,那么,按队列的操作应该将数列变为7,5,9,2。

然而单调队列就不一样。假设有一条队列7,6,3,4,现在又有一个数5要进队,却看见3,4都比5要弱~~(类似MYJ在某STAR中将LYH打爆的行为)~~,所以就有了一种类似插队的方法,5将3和4挤掉,来到了6的后面,构成了这种队列:
此处输入图片的描述

所以单调队列维护单调就是通过插队把队尾破坏了单调的数全部从队尾退队,使队列元素维持单调(单调队列与队列不同就是单调队列既可以从队首出队,也可以从队尾出队)。
看看一道模板
P1886 滑动窗口
据说可以用线段树,树状数组什么的,但单调队列是拯救蒟蒻的做法(逃

所以说,这道题到底怎么做?
其实只需要枚举所有的连续子序列,使用单调队列找出最大值。
开始乱搞写代码:

//我用的手写单调队列,但你要用STL的deque我也拦不住
#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[1000001]={0},q[10000001]={0};q数组表示单调队列,a表示其所对应的在原列表里的下标
int head=1;//头指针
int tail=1;//队尾指针
int main(){
	cin >> n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		while(head<tail&&a[q[tail-1]]>a[i]){
			tail--;//插队,将后面的数踢掉,以维护单调性
		}
		q[tail++]=i;//存编号
        while(head<tail&&q[head]<=i-k){
        	head++;//队首元素太old了,就出队。
		}
        if(i>=k){
        	cout <<a[q[head]]<< " ";//按题目要求的输出
		}
	}
	cout << endl;
	--------------------------------------------------------------------------------------------
	head=1,tail=1;

	for(int i=1;i<=n;i++){
		while(head<tail&&a[q[tail-1]]<a[i]){//队列中存在元素,又队尾元素比下一个处理的值大,即表示队尾元素太old,就让队尾元素出队。当队尾元素小于下一个处理值,单调性成立。
			tail--;
		}
		q[tail++]=i;//存编号
        while(head<tail&&q[head]<=i-k){
        	head++;//队首元素太old了,就出队。
		}
        if(i>=k){
        	cout << a[q[head]] << " ";//cout队首元素,即最大值
		}
	}
	cout << endl;
	return 0;
	//实际上分割线上下代码都差不多,只是维护单调性的while循环不一样
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值