zoukankan      html  css  js  c++  java
  • 单调队列入门

    参考博客:https://www.luogu.org/blog/ybwowen/dan-diao-dui-lie

    单调队列这个名字就指明了它的性质——单调性,是一个单调的双端队列

    下面列出deque的常用成员函数:来自:https://blog.csdn.net/morewindows/article/details/6946811

     单调队列入门题目:P1886 滑动窗口 /【模板】单调队列

     

    这里我们只讨论最大值,最小值原理一样的

    很明显,当我们在计算区间[ik+1,i]的最大值时,是不是区间[ik+1,i1]我们之前已经计算过了?那么我们是不是要保存上一次的结果呢(主要是最大值)?

    这时,单调队列登场——单调队列主要有两个操作:删头去尾

    1.删头

    如果队列头的元素离开了我们当前操作的区间,那么这

    个元素就没有任何用了,我们就要把它删掉

    2.去尾

    假设即将进入队列的元素为X,队列尾指针为tail这时我们要比较二者的大小:

    1* X<q[tail此时q仍然保证着递减性,故直接将X插入队列尾

    2*X>=q[tail此时,队列递减性被打破,此时我们做一下操作:

    ① 弹出队尾元素

    因为当前的q[tail]不但不是最大值,对于以后的情况也不如X,所以要弹出

    ②重复执行①,直到满足X<q[tail]X<q[tail]或者队列为空为止

    ③将XX入队列

    对于样例而言:

    [1 3 -1] -3 5 3 6 7 
    q={1},{3},{3,-1} output:3
    1 [3 -1 -3] 5 3 6 7 
    q={3,-1,-3} output:3
    1 3 [-1 -3 5] 3 6 7
    q={-1,-3},{-1,5},{5} output:5
    1 3 -1 [-3 5 3] 6 7
    q={5,3} output:5
    1 3 -1 -3 [5 3 6] 7 
    q={5,6},{6} output:6
    1 3 -1 -3 5 [3 6 7]
    q={6,7} output:7

    由于每个元素最多入队一次,出队一次,所以时间复杂度为O(n)

    当然,这题还可以用ST表和线段树来做,但都没有单调队列方便

    实现:由于要对队首和队尾进行维护,所以我们需要使用双端队列

    AC_Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1e6+10;
     5 const ll inf=0x3f3f3f3f3f3f3f3f;
     6 #define dep(i,first,last) for(int i=first;i>=last;i--)
     7 #define rep(i,first,last) for(int i=first;i<=last;i++)
     8 #define lson l,mid,pt<<1
     9 #define rson mid+1,r,pt<<1|1
    10 
    11 template<typename T>void read(T &a){
    12     T x=0,f=1;
    13     char ch=getchar();
    14     while( !isdigit(ch) ){
    15         if( ch=='-') f=0;
    16         ch=getchar();
    17     }
    18     while( isdigit(ch) ){
    19         x=(x<<1)+(x<<3)+ch-'0';
    20         ch=getchar();
    21     }
    22     a=f?x:-x;
    23 }
    24 
    25 deque<int>q;
    26 int a[maxn],n,m;
    27 int main()
    28 {
    29     read(n);
    30     read(m);
    31     rep(i,1,n) read(a[i]);
    32     rep(i,1,n){
    33         while(!q.empty() && a[q.back()]>a[i]) q.pop_back();
    34         q.push_back(i);
    35         if( i>=m ){
    36             while( q.front()<=i-m ) q.pop_front();
    37             printf("%d ",a[q.front()]);
    38         }
    39     }
    40     printf("
    ");
    41     while(!q.empty()) q.pop_front();
    42     rep(i,1,n){
    43         while(!q.empty() && a[q.back()]<a[i]) q.pop_back();
    44         q.push_back(i);
    45         if( i>=m ){
    46             while( q.front()<=i-m ) q.pop_front();
    47             printf("%d ",a[q.front()]);
    48         }
    49     }
    50     printf("
    ");
    51     return 0;
    52 }
  • 相关阅读:
    DBCC修复不同情况下的损坏
    Python单例模式的4种实现方法
    osx 安装redis
    tornado系列文章
    Python中__init__和__new__的区别详解
    Tornado源码分析之http服务器篇
    tornado.ioloop.IOLoop相关文章
    How to use POST method in Tornado?
    https://github.com/diogobaeder/pycket
    Frequently Asked Questions
  • 原文地址:https://www.cnblogs.com/wsy107316/p/12320847.html
Copyright © 2011-2022 走看看