• P1886 滑动窗口(单调队列)


    --------------------------

    题目链接:Miku

    --------------------------

    看一看这道题,我们很容易会发现采用模拟+遍历的方法会TLE

    这时,我们就要采用这样一个东西了——单调队列(其实这也就是个单调队列模板)

    ---------------------------

    单调队列,顾名思义,我们在使用时这个队列是有一定顺序(单调)的,并且它有一个特点,你的队列的极值一定在队首,知道这些,我们接可以做题了

    ---------------------------

    单调队列是从队尾插入,而队首,队尾都会删除的双端队列。以该题为例,我们首先需要一个降序的单调队列,但是怎么实现呢?

    假设此时队列为1,2,6,我们我们要插入一个4,显而易见,只要我们把4插进去,6就不可能是最小值了(反之就有可能),所以为了维护队列单调性,我们需要把6删除

        while(!q1.empty()&&q1.back()>=now)//注意,一定要把判断是否为空放在前面 
            {
                q1.pop_back();
                q2.pop_back();//弹出 
            }
    example

    看见提示了吗,在C++中,如果你返回一个空队列的值,就会RE,而且&&是短路运算符(简单来说,它会先判断左边的是否成立,成立再去判断右边),所以如果你反着放,c++会直接告诉你RE!而且右边的判断是否为空根本不会运算!!

    ------------------------

    现在,你明白了单调队列的基本操作

    ------------------------

     1 /*
     2 其实有时候了解一些C++特性也挺重要的
     3 
     4 因为很多时候会RE而不知所措
     5 
     6 但是或许就和原理有关 
     7 */
     8 
     9 #include<iostream>
    10 #include<queue>
    11 #include<deque>
    12 using namespace std;
    13 deque <int> q1,q2;
    14 int n,k;
    15 int a[1000001];
    16 int now;
    17 int main(){
    18     cin>>n>>k;
    19     for(int i=1;i<=n;++i)
    20     {
    21         cin>>a[i];
    22     }
    23     //处理一个升序单调队列 
    24     for(int i=1;i<=n;++i){
    25         now=a[i];//当前值 
    26         while(!q1.empty()&&q1.back()>=now)//注意,一定要把判断是否为空放在前面 
    27         {
    28             q1.pop_back();
    29             q2.pop_back();//弹出 
    30         }
    31         q1.push_back(now);//压入 
    32         q2.push_back(i);
    33         if(i-k>=q2.front())//这是判断头元素是不是应该被“抛弃 
    34         {
    35             q1.pop_front();
    36             q2.pop_front();
    37         }
    38         if(i>=k)//输出,一定要到了K在开始
    39         //你一定明白 
    40         {
    41             cout<<q1.front()<<" ";
    42         }
    43     }
    44     cout<<endl;
    45     q1.clear();
    46     q2.clear();//清空 
    47         for(int i=1;i<=n;++i){
    48         now=a[i];
    49         while(!q1.empty()&&q1.back()<=now)
    50         {
    51             q1.pop_back();
    52             q2.pop_back();
    53         }
    54         q1.push_back(now);
    55         q2.push_back(i);
    56         if(i-k>=q2.front())
    57         {
    58             q1.pop_front();
    59             q2.pop_front();
    60         }
    61         if(i>=k)
    62         {
    63             cout<<q1.front()<<" ";
    64         }
    65     }
    66     return 0;
    67 }
    68  
    AC

    -----------------------

    That is all.

  • 相关阅读:
    getBoundingClientRect介绍
    【vue移动端架子】vue-h5-template
    【vue】openshopping-vue
    【vuex】vue2-happyfri
    Google浏览器插件之闪存过滤器
    跟我一起写一个chrome扩展程序
    Windows Server AppFabric 安装文档
    提高entity framework 性能,要注意哪些事情.
    [Entity Framework]获取部分字段的查询
    EF多表查询方式
  • 原文地址:https://www.cnblogs.com/For-Miku/p/10962621.html
Copyright © 2020-2023  润新知