zoukankan      html  css  js  c++  java
  • 单调队列与dp的关系

    单调队列的介绍

    顾名思义,单调队列就是指递增或者递减的队列,经过维护之后,让队列元素的第一个始终是范围内的最大或者最小值

    其实现方法很多,可以开一个队列queue,或者直接在数组里用head和tail下标来完成

     1 void find_min()//求最小值的单调队列
     2 {
     3     int head = 0, tail = -1;
     4     for (int i = 0; i < n; i++)
     5     {
     6         if (head<=tail&&p[head] + k <= i) head++;//队列有元素,并且超出范围了,k是单调队列是多少个元素里最大,如果超出了这个值,那么队首元素就可以舍弃
     7         while (head <= tail && a[p[tail] ]>= a[i]) tail--;//队列有元素,要加入的值比队尾元素小,那么队尾元素就没有存在的意义了,因为我们要求的是最小值
     8         p[++tail] = i;//把要加入的值的坐标加入p[],p是记录下标的
     9         if (i + 1 >= k) cout << a[p[head]] << " ";//满足长度之后,输出才有意义
    10     }
    11 }
    12 void find_max()
    13 {
    14     int head = 0, tail = -1;
    15     for (int i = 0; i < n; i++)
    16     {
    17         if (head <= tail && p[head] + k <= i) head++;
    18         while (head <= tail && a[p[tail]] <= a[i]) tail--;
    19         p[++tail] = i;
    20         if (i + 1 >= k) cout << a[p[head]] << " ";
    21     }
    22 }

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

    单调队列和dp的关系

    dp有的时候要求遍历某些前面的dp值来求出目前的dp值

    如洛谷P3572 PTA-Little Bird

    很容易看出转移方程

    dp[j]=(前面范围内dp值最小的)+1/+0;

    我们只需判断前面范围内哪个值dp最小,在dp值相同的情况下让高度最高

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 using namespace std;
     5 const long long int MAX = 2000010;
     6 long long int a[MAX];
     7 long long int p[MAX];
     8 long long int n;
     9 long long int dp[MAX];
    10 deque<long long int>qq;
    11 int main()
    12 {
    13     ios::sync_with_stdio(false);
    14     cin.tie(0);
    15     cout.tie(0);
    16     long long int q,d;
    17     cin >> n;
    18     for (long long int i = 1; i <=n; i++)
    19     {
    20         cin >> a[i];
    21     }
    22     cin >> q;
    23     while (q--)
    24     {
    25         cin >> d;
    26         
    27         qq.clear();
    28        
    29         qq.push_back(1);
    30         for (long long int i = 2; i <= n; i++)
    31         {
    32             while (!qq.empty() && i - qq.front() > d) qq.pop_front();
    33             if (a[qq.front()] > a[i]) dp[i] = dp[qq.front()];
    34             else dp[i] = dp[qq.front()] + 1;
    35             while (!qq.empty() && (dp[qq.back()] > dp[i] || (dp[qq.back()] == dp[i] && a[qq.back()] <= a[i]))) qq.pop_back();
    36             qq.push_back(i);
    37         }
    38         cout << dp[n] << endl;
    39     }
    40     return 0;
    41 }

    总之,单调队列起到的是一个快捷找范围内最大最小的作用,适合数据较大的时候使用

  • 相关阅读:
    Leetcode 50.Pow(x,n) By Python
    Leetcode 347.前K个高频元素 By Python
    Leetcode 414.Fizz Buzz By Python
    Leetcode 237.删除链表中的节点 By Python
    Leetcode 20.有效的括号 By Python
    Leetcode 70.爬楼梯 By Python
    Leetcode 190.颠倒二进制位 By Python
    团体程序设计天梯赛 L1-034. 点赞
    Wannafly挑战赛9 C-列一列
    TZOJ Start
  • 原文地址:https://www.cnblogs.com/Knightero/p/12759360.html
Copyright © 2011-2022 走看看