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

单调队列

时间:2023-06-04 22:33:29浏览次数:26  
标签:return 队列 tt int hh void 单调

写法

首先要有一个双端队列:

struct My_dequeue{
    int hh=1,tt=0,q[N];
    void clear(){hh=1;tt=0;}
    void push_front(int k){q[--hh]=k;}
    void push_back(int k){q[++tt]=k;}
    void pop_front(){hh++;}
    void pop_back(){tt--;}
    int front(){return q[hh];}
    int back(){return q[tt];}
    int head(){return hh;}
    int tail(){return tt;}
    bool empty(){return hh>tt;}
}q;

以下给出单调队列的标准写法。

int calc(int i){//返回下标对应的值
    return inp[i];
}

void insert(int x){//传入下标
    while(!q.empty()&&calc(q.back())<=calc(x)) q.pop_back();//维护最大值
    q.push_back(x);//存入下标
}

int query(int x){
    while(q.front()<=x-k) q.pop_front();//弹出不符合条件的下标
    return calc(q.front());//返回值
}

q.clear();
for(int i=1;i<=n;i++){
    insert(i);
    ans[i]=query(i);
}

作用

维护左右端点单调的若干定长连续区间的 RMQ。

可以用于优化 DP 。要求当前状态的所有值可以从上一个状态的某个连续的段的值得到,将要对这个连续的段进行 RMQ 操作,且相邻状态的段的左右区间满足非降的关系。

具体的说,要求 DP 的状态转移方程满足以下形式( \(b\) 为任意与\(k\)无关的式子,\(x,y\) 为任意与$j $无关的式子):

\[f(i,j)=\max\{f(i-1,k)\}+b,k\in[j-x,j+y] \]

\[f(i)=max\{f(k)\}+b,k\in[i-x,i-y],x>0,y>0 \]

那么,就可以通过单调队列优化其时间复杂度。

具体的说,我们可以用单调队列维护上一层的 DP 数组的区间最值。由于每一层内求最值的区间长度固定,就可以仿照上面的写法将其构造成一个单调队列,计算新状态时就可以以均摊 \(O(1)\) 的时间复杂度维护最值信息,这样总时间复杂度就可以少一个 \(n\)。是一个优秀的优化。

单调队列优化通常配合滚动数组一起适用,可以让时空均少一个 \(n\)。

例如:

\[f(i)=max\{f(k)\}+a[i],k\in[i-R,i-L] \]

那么代码是这样的:

int calc(int i){//返回下标对应的值
    return f[i];
}

void insert(int x){//传入下标
    while(!q.empty()&&calc(q.back())<=calc(x)) q.pop_back();//维护最大值
    q.push_back(x);//存入下标
}

int query(int x){
    while(q.front()<=x-R-1) q.pop_front();//弹出不符合条件的下标
    return calc(q.front());//返回值
}

q.clear();
for(int i=L;i<=n;i++){
    insert(i-L);
    f[i]=query(i)+a[i];
    if(i+R>n) ans=max(ans,f[i]);
}

标签:return,队列,tt,int,hh,void,单调
From: https://www.cnblogs.com/TKXZ133/p/17456548.html

相关文章

  • jQuery队列控制方法详解queue()/dequeue()/clearQueue()
    jQuery遍历-jQuery.queue()方法:[url]http://www.w3school.com.cn/jquery/data_jquery_queue.asp[/url]jQuery核心中,有一组队列控制方法,这组方法由queue()/dequeue()/clearQueue()三个方法组成,它对需要连续按序执行的函数的控制可以说是简明自如,......
  • 3.两种模式与交换机和队列的属性
    5.两种模式5.1.Confirm介绍消息的confirm确认机制,是指生产者投递消息后,到达了消息服务器Broker里面的exchange交换机,则会给生产者一个应答,生产者接收到应答,用来确定这条消息是否正常的发送到Broker的exchange中,这也是消息可靠性投递的重要保障5.2.Confirm使用5.2.1.环境搭建......
  • Linux 内核等待队列
    Linux内核中的等待队列是一种延时机制,其用于当前进程需要等待某些资源而进入一种sleep状态,当等待条件为真时,进程被唤醒,继续执行。显然,这里涉及三个方面,即,一是等待时当前进程处理,二是进程等待时所关注的资源处理,三时进程何时被唤醒继续执行。所以,我们这里需要几个数据结构,主要描......
  • 2.交换机与特殊队列
    2.交换机2.1.类型1.FanoutExchange(扇形)2.DirectExchange(直连)3.TopicExchange(主题)4.HeadersExchange(头部)以下类型的交换机使用都会使用到这两个步骤①选择依赖②修改启动类2.2.FanoutExchange2.2.1.介绍FanoutExchange:扇形交换机投递到所有绑定的队列,不需要路由键,不......
  • 初级数据结构--栈、队列
    栈后端(进栈)插入,后端(出栈)删除顺序存储,用静态数组实现,需要记录栈顶指针,栈的增删操作只能操作栈顶的护数据。两种初始化方式top=-1top=0共享栈两个栈共用一片内存空间,两个栈从两边向中间增长初始化1个栈顶指针初始为-1;另一个栈顶指针初始为Maxsize栈满条件 top0+1==top1队列后端(......
  • 两个栈实现队列
    @TOC一、栈和队列的基本特点栈的特点是后进先出,而队列的特点是先进先出。使用两个栈实现队列,必须具备队列的先进先出的功能。举个例子:向其中一个栈中放入4个元素,那么按照队列的特点,出队时是1先出队,所以需要把栈的所有元素全部出栈转移到空栈中。再逐一出元素。假如出栈一次后,又需......
  • 消息队列RocketMQ基本概念
     1消息模型(MessageModel)RocketMQ主要由Producer、Broker、Consumer三部分组成,其中Producer负责生产消息,Consumer负责消费消息,Broker负责存储消息。Broker在实际部署过程中对应一台服务器,每个Broker可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不......
  • 剑指 Offer 09. 用两个栈实现队列
    剑指Offer09.用两个栈实现队列</br></br>题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead操作返回-1)示例1:输入:["CQueue","appendTail",......
  • php rabbitmq队列的几种管理方案
     这里就懒得记录了,直接放上一篇还不错的知乎博主的博客吧。点击前往  ......
  • 使用两个队列实现栈
    @TOC前言本文章主要介绍栈和队列的相互转换。使用两个队列实现栈我们知道,栈的特点是后进先出,而队列的特点是先进先出。栈的特点:队列的特点:使用两个队列实现栈的思路是:1.向两个队列中的任一队列放入元素2.取出元素时,队列的功能是先进先出,要达到后进先出,需要将前面的所有元素取出,存入......