• Hlg 1522 子序列的和 <单调队列>


    题意:

    给一串数字长度n 和 取值长度范围m

    还有这串数字..a0, a1, a2, a3, ..., an

    求这串数字中在 长度范围m 内和sum 最大的..

    思路:

    从1~n 遍历每一个数..

    当前数字串和S(i) - 以前数字串和中的最小那个S(i-k){1 < k <m}<以前数字串的‘以前’范围是取值长度范围>

    ‘以前数字串和中的最小那个’可以用 单调队列que 来控制..

    取遍历结果中最小那个..

    Tips:

    主要讲一下什么是单调队列..

    单调队列..顾名思义就是 单调增或减的队列..它存的值是对应 和数组s 里的下标..

    其中队头元素是 队列s 最大值或最小值的下标..

     

    但是其实这个队列不是实际存在的..

    而是用在一个大队列里..找出符合条件的单调小队列..

    然后根据这个单调小队列来解题..

    找单调小队列靠一个队头指针front 和 一个队尾指针 rear

     

    把下标加入一个大的队列里..

    然后根据条件调整队头指针和队尾指针..

    而条件就是

    ①. 队头元素:在 front指针 <= rear 指针的前提下.. 队头元素的下标在给定范围内..

    ②. 队尾元素:在 front指针 <= rear 指针的前提下.. 若是单调递增队列..即队头元素是最小的..so..新插入的队尾元素的值应该要比原队尾的值大..保证插入新队尾元素后这个队列还是单调递增队列..

                                                                    若是单调递减队列..即队头元素是最大的..so..新插入的队尾元素的值应该要比原队尾的值小..保证插入新队尾元素后这个队列还是单调递减队列..

     

    eg:

    假设数列为:8,7,12,5,16,9,17,2,4,6.N=10,k=3.

    那么我们构造一个长度为3的单调递减队列:

    首先,那8和它的索引0放入队列中,我们用(8,0)表示,每一步插入元素时队列中的元素如下:

    0:插入8,队列为:(8,0)

    1:插入7,队列为:(8,0),(7,1)

    2:插入12,队列为:(12,2)

    3:插入5,队列为:(12,2),(5,3)

    4:插入16,队列为:(16,4)

    5:插入9,队列为:(16,4),(9,5)

    。。。。依此类推

    那么f(i)就是第i步时队列当中的首元素:8,8,12,12,16,16,。。。

    例子自【转】自:http://blog.csdn.net/Justmeh/article/details/5844650#reply    感觉博主讲得挺详细挺清楚的..就是code貌似有点问题..

     

    最后这道题单调小队列的结果就是 在 取值长度范围m 内和单调递增的 对应下标值..

    Code:

    View Code
     1 #include <stdio.h>
     2 #include <cstring>
     3 #define clr(x) memset(x, 0, sizeof(x))
     4 
     5 int que[100010];
     6 int s[100010];
     7 
     8 int buffer(int n, int len)
     9 {
    10 
    11     int i, j, k;
    12     int front = 0, rear = -1;
    13     int res = -99999999;
    14 
    15     for(i = 1; i <= n; ++i){
    16         while(front <= rear && que[front] < i-len)
    17             front++;
    18 
    19         while(front <= rear && s[i-1] < s[que[rear]])
    20             rear--;
    21 
    22         que[++rear] = i-1;
    23 
    24         if(res < s[i]-s[que[front]])
    25             res = s[i]-s[que[front]];
    26     }
    27 
    28     return res;
    29 }
    30 
    31 int main()
    32 {
    33     int i, j, k;
    34     int num;
    35     int n, m;
    36     while(scanf("%d %d", &n, &m) != EOF)
    37     {
    38         clr(que);
    39         clr(s);
    40         for(i = 1; i <= n; ++i){
    41             scanf("%d", &num);
    42             s[i] = s[i-1]+num;
    43         }
    44 
    45         printf("%d\n", buffer(n, m));
    46     }
    47     return 0;
    48 }

     

  • 相关阅读:
    iOS开发 数据缓存-数据库
    我是程序猿,我自豪,我骄傲!嗷嗷嗷!
    【Golang】练习-复制文件
    【Golang】练习-读取目录下的文件并按时间进行排序
    【Golang】练习 tailf 简单模拟
    【Golang】基础-切片 for 循环删除元素
    【Golang】基础-操作 csv 文件
    【Golang】Godoc 或者第三方 plugins 插件介绍
    【Golang】类型转换之 cast 包
    【Golang】解决 go get下载包慢或者失败的问题
  • 原文地址:https://www.cnblogs.com/Griselda/p/2632428.html
Copyright © 2020-2023  润新知