首页 > 其他分享 >单调队列

单调队列

时间:2024-05-19 16:40:59浏览次数:30  
标签:le Min 队列 ed int num 单调 dp

单调队列

考虑在一个序列中维护一个类似于窗口的东西。

以下不妨设求得是窗口最大值。

首先根据贪心,如果当前数整个窗口中最大的,并且是最靠前的,那么这个数前面的所有数都不会对答案产生一点贡献。于是考虑维护一个单调递增的序列,需要从中找出答案。设置一个首指针,未指针代表这个窗口的开始和结束。

然后,考虑一个和莫队类似的操作:

Remove 操作:将比当前值小的数扔出维护序列即可。

Add 操作:直接将当前数加入到队伍的最后段(这里可以仔细想一想,为什么)。

然后按照这样的操作模拟即可。

时间复杂度分析

这是很简单的,因为每一个元素最多只被出队和入队各 \(1\) 次,所以时间复杂度是 \(O(n)\)。

模板

模板题目:P1886 滑动窗口

AC code

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1000;
int n,k;
int number[N];
int num[N];

int main(){
	ios::sync_with_stdio(0);
	cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>number[i];
	int fst=0,ed=-1;
	for(int i=1;i<k;i++){
		while(fst<=ed&&number[num[ed]]>=number[i])ed--;
		num[++ed]=i;
	}
	for(int i=k;i<=n;i++){
		while(fst<=ed&&number[num[ed]]>=number[i])ed--;
		num[++ed]=i;
		while(num[fst]<=i-k)fst++;
		cout<<number[num[fst]]<<' ';
	}
	for(int i=0;i<=ed;i++)num[i]=0;
	fst=0,ed=-1;
	cout<<'\n';
	for(int i=1;i<k;i++){
		while(fst<=ed&&number[num[ed]]<=number[i])ed--;
		num[++ed]=i;
	}
	for(int i=k;i<=n;i++){
		while(fst<=ed&&number[num[ed]]<=number[i])ed--;
		num[++ed]=i;
		while(num[fst]<=i-k)fst++;
		cout<<number[num[fst]]<<' ';
	}
	return 0;
}	

优点分析

单调队列可以在 \(O(n)\) 的时间复杂度之内求出一个给定区间长度的整个序列中的区间最大值,在这一点上,它比 线段树ST表 优化了一个 \(O(\log n)\) 的时间。

例题

P2698

题目形式化:

  • 给出一条线段上的 \(n\) 个点,每个点有一个权值 \(

    标签:le,Min,队列,ed,int,num,单调,dp
    From: https://www.cnblogs.com/Pump-kin/p/18200460

相关文章

  • 一个Java基于阻塞的定时消费内存队列
     @Getter@AllArgsConstructorpublicenumInsertQueueEnum{A(30000,10,TimeUnit.SECONDS,2,1000),;privatefinalintcapacity;//队列长度privatefinalinttime;//最长阻塞时间privatefinalTimeUnittimeUnit;//最长阻塞时间单位privatefi......
  • 【CodeChef】3out1in(优先队列)
    题目大意:给出数组a,问对于所有满足\(1\lek\len\)的奇数\(k\),\(f([a_1,a_2,...,a_k])\)的值。\(f([a_1,a_2,...,a_n])\)的值为对数组\([a_1,a_2,...,a_n]\)进行\(\frac{n+1}{2}\)次操作(选择数组中的三个元素,将其中一个取相反数,然后让它们合并成一个元素)后,数组最后剩下元素的最大......
  • 单调栈的使用
    以leetcode739为例,我们利用单调栈维护一个单调递增数列https://leetcode.cn/problems/daily-temperatures/description/ 通过上述内容,我们一直通过栈顶读取元素,维护数列的单调性。Q:单调栈用于做什么A:求每个元素左(右)侧第一个比他小(大)的元素的位置(具体值)单调栈的维护和操作都......
  • 单调栈
    单调栈:可以线性预处理:序列前/后缀最大/小值的位置,或者是第\(i\)个数下一个更小/大数的位置。B3666求数列所有后缀最大值的位置https://www.luogu.com.cn/problem/B3666题意:给一个初始为空的数列\(a\),共\(n\)次操作,第\(i(1\leqi\leqn)\)次操作会在\(a\)的末尾......
  • kombu & celery:如何在Python中舒适地使用消息队列
    Kombu和Celery是Python中的两个库,它们可分开或结合起来使用,以实现基于分布式消息传递的异步任务队列。KombuKombu是一个Python消息库,它为多种消息队列提供了抽象和统一的使用方式。它支持AMQP协议的消息队列服务,如RabbitMQ和Redis,以及其他一些通过插件实现的传输方......
  • 线程安全队列(使用互斥锁进行实现)
    线程安全队列(使用互斥锁进行实现)没有设置队列上限的线程安全队列只需要采取一个std::condition_variable变量,用于处理队列为空的情况以下是示例代码,涉及了std::mutex和std::condition_variable、std::unique_lock、std::lockguard等多线程交互的类。测试方式采取的是3个生成者......
  • PikaScript - 面向嵌入式的超轻量级python引擎+Ring-Buffer - 仅80行代码的超简洁环形
    1、PikaScript-面向嵌入式的超轻量级python引擎PikaScript(前称mimiscript)是一个完全重写的超轻量级python引擎,零依赖,零配置,可以在少于4KB的RAM下运行(如stm32g030c8和stm32f103c8),极易部署和扩展。项目地址:https://github.com/pikasTech/pikascriptPikaScript是使用c语言写......
  • 力扣-232. 用栈实现队列
    1.题目信息2.题解2.1双栈的使用(用栈实现队列)思路我们一开始可能会想到对于每次入栈操作——由于我们可能希望他是加在队尾(栈底)而不是队头(栈首),所以我们就进行一次首尾互换,将instack中的数据倒腾到outstack,由于栈先进后出的特性,所以这时候原来的栈底在头部,我们直接将元素pus......
  • 实现队列 栈 双端队列
    以下都是用list来实现的 实现Stack#ImplementaStackinPythonclassStack(object):def__init__(self):self.items=[]defis_empty(self):returnself.items==[]defpush(self,item):self.items.append(item)d......
  • 算法竞赛第一章-队列
    1、队列constintN=1e5;//定义队列大小intque[N],head,tail;//队头队尾指针,队列大小为tail-head+1//head++;弹出对头,head<=tail//queue[head];//读对头数据//que[++tail]=data;//数据data入队,尾指针加1,注意不能溢出2、STLqueuequeue<Type>q:定义......