单调队列

单 于 十 万 貔 貅 拥
调 燮 千 金 一 丈 夫
队 队 鱼 龙 真 乐 事
列 仙 何 必 问 江 湖

单 于 车 骑 来
调 鼎 出 蓬 莱
队 队 人 千 里
列 仙 酒 一 杯
看看这两首诗每句话的开头,连起来就是单调队列,单调队列是一个好东西啊,他在各路算法中间都有极大的用处,特别是用来卡时间,优化算法,所一不学好是不行的啊。

现在开始正式讲一讲单调队列
首先来看一看一道题
滑动窗口
乍一看,不是线段树吗?随随便便就过了,但是速度十分慢,而且这只是训练单调队列的一道题而已

用一个头指针,一个尾指针,模拟,满足每次队列满足单调性。
新的数从尾部加入,如果大于等于前面一个数则弹出前一个数,tail++,直到不满足条件,在尾部放入这个数。
是不是很绕?

现在将它具体化,假设有一个oier在机房颓游戏,导致忘记了它接下来还有课外班,可怜,残酷。等他想起来已经要上课了,于是他飞奔至公交站台,好不容易等到车来了,但是发现上车人太多了。他决定采取一些措施,已知每个人都有一个武力值。如果他的武力值大于前面的人,直接将他扔到后面去,自己则向前一位,如此反复。如果等于,因为他心中有着一个抢座位的信念,所以经过殊死搏斗,还是把那人扔后面去了。

是不是理解了,接下来看代码
代码如下:

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define rg register
using namespace std;
struct node{
	int v,x;
}Max[1000001],Min[1000001];
int a[1000001];
inline int read(){
	int x=0,c=getchar(),f=1;
	while(c<'0'||c>'9')
		f= (c=='-')?-1:1,c=getchar();
	while(c>='0'&&c<='9')
		x=x*10+c-48,c=getchar();
	return f*x;
}
inline void print(int x){
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        print(x/10);
    putchar(x%10+'0');
}
int main(){
	int n,m;
    rg int head=1,tail=1;
	n=read(),m=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	for(rg int i=1;i<=n;i++){
		while(Min[tail].v>=a[i]&&head<=tail)
			tail--;
		tail++,Min[tail].x=i,Min[tail].v=a[i];
		if(i<m)
			continue;
		int flag=0;
		while(head<=tail){
			(Min[head].x>=i-m+1)?(print(Min[head].v),putchar(' '),flag=1):head++;
			if(flag==1) break;
		}
	}
	putchar('\n');
	head=tail=1;
	for(rg int i=1;i<=n;i++){
		while(Max[tail].v<=a[i]&&head<=tail)
			tail--;
		tail++,Max[tail].x=i,Max[tail].v=a[i];
		if(i<m)
			continue;
		int flag=0;
		while(head<=tail){
			(Max[head].x>=i-m+1)?(print(Max[head].v),putchar(' '),flag=1):head++;
			if(flag==1) break;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值