• 单调队列


    单调队列,顾名思义,是一个队列且具有单调性!!(严格单调递增或递减,以下讨论单调递增,递减相同)

    假设一组输入数据:3 2 1 4 5 6 3 4

    执行过程:从队尾开始比较,若队尾元素大于等于当前元素,则删除队尾元素,队尾指针前移,并继续比较直到队尾元素小于当前元素,把当前元素加入队尾

    则单调队列中的情况如下:

    1)3

    2)2         //因为2小于3,为了维护单调递增的性质,所以从队尾删掉3,并加入2,下同

    3)1

    4)1  4

    5)1  4  5

    6)1  4  5  6

    7)1  3

    8)1  3  4

    最后队列里的数就是:1  3  4

    单调队列本身概念很简单,性质也挺好理解的。以前却一直不知道怎么用。

    最近看了一篇后缀数组的应用,里面讲用单调队列维护height数组的时候,提了一下单调队列,写得挺不错的。

    原来要加一个“时间戳”,再加上双端队列的操作,才能让它更强大。

    就拿poj的2823来说,其中的视窗操作正好对应了这个“时间戳”——数组下标。

    如果当前元素的下标减去队首元素的下标大于视窗大小,则这个元素肯定在视窗外,应该被舍去,继续检查队首元素,直到队首元素在视窗以内。

    这个“时间戳”概念真的挺重要的!

    poj - 2823
     1 #include <stdio.h>
    2 #include <string.h>
    3 #include <iostream>
    4 using namespace std;
    5
    6 #define N 1000010
    7
    8 struct node{
    9 int m, d;
    10 }Inc[N], Dec[N];
    11
    12 int mi[N], mx[N], num, k;
    13
    14 bool cmpMAX(const int &a, const int &b){ return a>b; }
    15 bool cmpMIN(const int &a, const int &b){ return a<b; }
    16
    17 void chk(int i, int &head, int &tail, node c[], bool cmp(const int &a, const int &b))
    18 { //添加新节点到队尾,并删掉过期的头节点
    19 while(tail >= head && cmp(c[tail].m, num)) tail--;
    20 c[++tail].m = num;
    21 c[tail].d = i;
    22 while(cmpMAX(i-c[head].d+1, k)) head++;
    23 }
    24 void solve()
    25 {
    26 int n, i, j, id=0;
    27 int head_I=0, tail_I=0, head_D=0, tail_D=0;
    28
    29 scanf("%d%d", &n, &k);
    30 if(n>0 && k>=1) //初始化化队列里的第一个点
    31 {
    32 scanf("%d", &num);
    33 Inc[0].m = Dec[0].m = num;
    34 Inc[0].d = Dec[0].d = 0;
    35 }
    36 for(i=1; i<k; i++) //初始化视窗中的点: 加入队列
    37 {
    38 scanf("%d", &num);
    39 chk(i, head_I, tail_I, Inc, cmpMIN);
    40 chk(i, head_D, tail_D, Dec, cmpMAX);
    41 }
    42 mi[id] = Inc[head_I].m;
    43 mx[id++] = Dec[head_D].m;
    44 for(; i<n; i++) //添加并更新
    45 {
    46 scanf("%d", &num);
    47 chk(i, head_I, tail_I, Inc, cmpMIN);
    48 chk(i, head_D, tail_D, Dec, cmpMAX);
    49 mi[id] = Inc[head_I].m;
    50 mx[id++] = Dec[head_D].m;
    51 }
    52 printf("%d", mx[0]);
    53 for(i=1; i<id; i++) printf(" %d", mx[i]);
    54 printf("\n%d", mi[0]);
    55 for(i=1; i<id; i++) printf(" %d", mi[i]);
    56 printf("\n");
    57 }
    58
    59 int main()
    60 {
    61 solve();
    62 return 0;
    63 }


    (待补充)

  • 相关阅读:
    Joomla 3.9.13 二次注入分析(CVE-2019-19846)
    Wordpress未授权查看私密内容漏洞 分析(CVE-2019-17671)
    Thinkphp 5.1.24 parseKey缺陷导致聚合注入 分析
    Thinkphp 5.1.7 parseData缺陷导致insert/update注入 分析
    Oracle笔记2
    Oracle笔记1
    k8s之helm入门
    k8s之自定义指标API部署prometheus
    k8s之资源指标API部署metrics-server
    k8s之调度器、预选策略及优选函数
  • 原文地址:https://www.cnblogs.com/Nstd/p/2249234.html
Copyright © 2020-2023  润新知