从0开始学算法--数据结构(2.4双端队列与单调队列)

双端队列是特殊的队列,它与队列不同的是可以将元素加入头或尾,可以从头或尾取出元素(滑稽-这部就是栈和队列结合了吗)。

c++标准库

头文件

#include<deque>

定义

deque<int>deq;

取出队头,尾元素

deq.pop_front();
deq.pop_back();

访问队头,尾元素

deq.front();
deq.back();

向队头,尾加入元素

deq.push_front(x);
deq.push_back(x);

单调队列是在队列的基础上使它保持有序,与单调栈类似,所以它反应的也是一个区间内的最值问题

例:poj-2823


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <deque>
#include <map>

using namespace std;

const int maxn=1e6+10;
int a[maxn];
int b[maxn];

struct aa{
    int a;
    int i;
    aa(){}
    aa(int x,int y):a(x),i(y){}
};
deque<aa>x;

int n,m;

int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=0;i<m-1;i++){
        if(x.empty())x.push_back(aa(a[i],i));
        else{
            aa w=x.back();
            while(!x.empty()&&w.a>=a[i]){
                x.pop_back();
                if(!x.empty())
                    w=x.back();
            }
            x.push_back(aa(a[i],i));
        }
    }
    int k=0;
    for(int i=m-1;i<n;i++){
        aa w;
        if(!x.empty())w=x.front();
        while(!x.empty()&&w.i<=i-m){
                //printf("%d ",w.a);
            x.pop_front();
            if(!x.empty())
                w=x.front();
        }
        if(x.empty())x.push_back(aa(a[i],i));
        else{
            w=x.back();
            while(!x.empty()&&w.a>=a[i]){
                    //printf("%d ",w.a);
                x.pop_back();
                if(!x.empty())
                    w=x.back();
            }
            x.push_back(aa(a[i],i));
        }
        w=x.front();
        b[k++]=w.a;
    }
    for(int i=0;i<k;i++){
        if(i!=k-1)printf("%d ",b[i]);
        else printf("%d\n",b[i]);
    }

    while(!x.empty())x.pop_back();

    for(int i=0;i<m-1;i++){
        if(x.empty())x.push_back(aa(a[i],i));
        else{
            aa w=x.back();
            while(!x.empty()&&w.a<=a[i]){
                x.pop_back();
                if(!x.empty())
                    w=x.back();
            }
            x.push_back(aa(a[i],i));
        }
    }

    k=0;
    for(int i=m-1;i<n;i++){
        aa w;
        if(!x.empty())w=x.front();
        while(!x.empty()&&w.i<=i-m){
                //printf("%d ",w.a);
            x.pop_front();
            if(!x.empty())
                w=x.front();
        }

        if(x.empty())x.push_back(aa(a[i],i));
        else{
            w=x.back();
            while(!x.empty()&&w.a<=a[i]){
                    //printf("%d ",w.a);
                x.pop_back();
                if(!x.empty())
                    w=x.back();
            }
            x.push_back(aa(a[i],i));
        }
        w=x.front();
        b[k++]=w.a;
    }
    for(int i=0;i<k;i++){
        if(i!=k-1)printf("%d ",b[i]);
        else printf("%d\n",b[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wz-archer/p/11712243.html

时间: 2024-11-09 23:13:41

从0开始学算法--数据结构(2.4双端队列与单调队列)的相关文章

从0开始学算法--数据结构(2.3队列)

顾名思义:队列就像排序一样,先排队的人先得到处理 队列与栈类似:队列是一个先进先出表 首先考虑数组模拟,如果线性数组模拟,会导致占用空间过多,为什么?数组模拟栈会遇到这样的问题吗? 因为队列是一个先进先出表,比如加入5个元素占用的是数组下表的0-4号位置,这时候删除两个元素,0-1号位置.为了维护这个队列的结构就会导致0-1号位置占用但不利用. 栈取出的是数组尾部的元素,所以不会占用额外的空间. 优化:“将数组变为环形”(模的意义). 如果我们每次加入元素是给数组下表取模,那么整个数组就变成了环

0基础学算法 第二弹 排序

大家好啊,这是0算法基础学算法系列第二篇,上次我在第一弹里讲了关于流程图的内容,我寻思着,这次讲些什么好呢,于是我决定,教大家一个很基础的算法,那就是排序,排序有很多方法,如果你有更多方法请在评论区里留言哦. 排序在程序中特别实用,常用的有快速排序,桶排序,冒泡排序,插入排序等等,在这里我不建议使用冒泡排序或者插入排序,建议桶排序和快速排序,这两个排序非常实用,时间复杂度低,理解起来也很容易,首先,你先思考一下,怎么用程序进行排序,然后你再来看看你的思路合理不合理,最后试着用程序实现它,实现后你

Redis源码-数据结构之Adlist双端链表

Redis的Adlist实现了数据结构中的双端链表,整个结构如下: 链表节点定义: typedef struct listNode { struct listNode *prev; struct listNode *next; void *value; } listNode; 链表定义: typedef struct list { listNode *head; listNode *tail; void *(*dup)(void *ptr); void (*free)(void *ptr); i

从0开始学算法--基础数据结构(2.8并查集)

算法理解: 根据名字就能很好的理解这个算法,集合的合并和查询 合并什么?查询什么? 合并操作为:把x所在的集合和y所在的集合合并为一个集合.查询x和y是否在一个集合里. 如:元素为1-n,这n个元素分别在编号为1-n的集合中.如果将3和5合并成为一个集合,只需要将元素3指向元素5即可 现在把元素5和元素2所在的集合合并合并,5指向2 可以看到如果要查询2和3是不是在一个集合中,只需要查询2和3的祖先是不是同一个元素就可以了 查询祖先代码 //f[x]初始化为f[i]=i; int find_se

从0开始学算法--排序(1.5归并排序)

算法理解: 一个数组长度为n,他的前m个元素是升序的,后n-m个元素升序的,怎么使整个数组变成一个升序数组? 如n=6,m=3 1 3 5 2 4 6 1 2 3 4 5 6 排序前 排序后 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <cmath> #include &

从0开始学算法--排序(1.7快速排序)

算法理解: 对于无序数组里的任意一个数字V,总有一部分数字小于V,一部分数字大于V.如果我们将比V小的数字放在V的前面,比V大的数字放在后面,那V所在的位置就是整个数组排序后V应该在的位置. 同时我们得到了两个连续的无序数组,和归并排序一样左右递归处理即可. #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio>

从0开始学算法--排序(1.8桶排序)

算法理解: 桶排序是对计数排序的一种优化,在计数排序中x应该放在计数数组下表为x的位置上,这样如果重复数字较少,计数数组每个位置的利用率就非常小. 桶排序是将一系列大小近似的数字放在一个位置(每个桶维护一条有序的链表),这样提高每个位置的利用率,以提高效率. 以A[]={1,21,23,41,49}为例 假设每个桶里有10中元素,那么桶排序的结构如下图所示. #include <algorithm> #include <iostream> #include <cstring&

从0开始学算法--排序(1.12c++利用标准库排序)

1,简单数组按升序排序 sort(a,a+n); #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <cmath> #include <queue> using namespace std; const int maxn=1e5+10; int a[maxn]; i

0基础学算法 第五弹 填坑

这个填坑系列,是为了能够解决大家在前面的疑点,如果你在前面有哪些疑点,可以加入QQ群1031467671,群名称叫球君博客的填坑群,入群问题答案是 球君,我要是在博客里有什么不足的,或着有什么讲的不清楚的地方,可以进去发表建议,好今天这期我就来填坑了,昨天有人说第四弹的乘法思路没讲清楚,所以今天我重新讲讲. 乘法的思路简单的说就是还是依靠竖式的原理,有第二个数的第一位乘上上面的全部数,再让第二个数的第二位乘上上面所有的数,这个操作用一个嵌套循环就可以完成了,再是进位问题,这个进位和加法有些不同,