蒟蒻的单调队列orz,真的蒻

(……打了这么久orz我今天才知道这玩意是啥意思……)

没有老师就是飘啊……我居然学完树状数组和线段树连个队列都不会……orz orz orz

这篇是单调队列哦,不是优先队列(优先队列那种东西queue不就好了嘛

咳咳咳废话说的真多,回到正题

什么是单调队列

咳咳咳反正是给自己看的,直接举个例子吧,比如一个从小到大的单调队列,那么这个队列中的每个元素的下标应符合递增,每个元素也应该符合递增

跟优先队列的区别应该是能看出来的吧……优先队列基本上就是排序好的数组了……(其实这么说,只是因为我不知道该怎么解释

单调队列的算法思想

原始数组

下标12345
42563

 

假如我们现在要将这整个数组加入从小到大的单调队列q

首先队列必备的两个指针:head  tail

队列本来为空,所以第一个元素直接入队,tail++

下标1
4

第二个元素2要入队了,但这时候我们发现2<4,那么如果将2直接加入队列,显然不符合其递增的单调性,所以我们干掉它的前一个元素(嘤嘤嘤就是这么暴力),tail--,再把2入队,tail++

下标1
2

第三个元素是5,5>2,符合其单调性,所以5直接入队tail++

下标12
25

第四个元素是6,同上一步

下标123
256

最后一个元素是3,同第二步,若要将3加入队列,不仅要干掉前面的6,tail--,前面的5也不能留!tail--(嗯就是这么凶

这时候的队列就变成了这个样子

下标12
23

ok,操作完成啦✿✿ヽ(°▽°)ノ✿

代码实现

结合我们刚刚的算法思想,我们就可以来搞一搞代码了QwQ

(s数组保存的是下标)

#include<bits/stdc++.h>
using namespace std;
int a[1000100],q[1000100],s[1000100]; 
int main()
{
	int n,k,tail,head;
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	head=1;
	tail=0;
	for (int i=1;i<=n;i++)
	{
	//	cout<<"现在出场的是:"<<i<<endl; 
		while (tail>=head&&a[i]<=q[tail])
		{
	//		cout<<"出队(tail):"<<s[tail]<<' '<<q[tail]<<endl;
			tail--;
		}
		tail++;
		q[tail]=a[i];
		s[tail]=i;
		while (s[head]<i-k+1)
		{
	//		cout<<"出队(head):"<<s[head]<<' '<<q[head]<<endl;
			head++;
		}
	//	cout<<"现在的队首是"<<s[head]<<"   "<<q[head]<<endl;
		if (i>=k)
			printf("%d ",q[head]);
	} 
	printf("\n");
	head=1;
	tail=0;
	for (int i=1;i<=n;i++)
	{
		q[i]=0;
		s[i]=0;
	}
	for (int i=1;i<=n;i++)
	{
	//	cout<<"现在出场的是:"<<i<<endl; 
		while (tail>=head&&a[i]>=q[tail])
		{
	//		cout<<"出队(tail):"<<s[tail]<<' '<<q[tail]<<endl;
			tail--;
		}
		tail++;
		q[tail]=a[i];
		s[tail]=i;
		while (s[head]<i-k+1)
		{
	//		cout<<"出队(head):"<<s[head]<<' '<<q[head]<<endl;
			head++;
		} 	
	//	cout<<"现在的队首是"<<s[head]<<"   "<<q[head]<<endl;
		if (i>=k)
			printf("%d ",q[head]);
	} 
	printf("\n");
	return 0;
}

我手头上没有纯裸题QwQ(其实就是懒QwQ)(咳咳主要是快下课了我想赶紧把这篇写完)

这篇是【传送门】洛谷1886 滑动窗口 的AC代码

其实就是两个裸单调队列加上队首出队操作而已,挺裸的一道题

(PS:调程序的时候我才知道!原来scanf不加&会.exe停止运行!printf加了&会输出奇奇怪怪的东西!!!(好吧其实还是我蒻))

但我在这里强烈安利一位大佬的题解QwQ!我就是看着他的题解学的单调队列!这里贴一下地址以便自己以后膜或者大家参观QwQ(我这惨淡的访问量到底是哪来的信心……https://www.luogu.org/blog/hankeke/solution-p1886

好啦!完结撒花✿✿ヽ(°▽°)ノ✿

 

【总有一天我会把我学过的所有算法和所有写过的模板题都写成博客的!!!这是一个 真flag】

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值