• 1201 最大子序和 (单调队列)


    描述

    输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。

    例如 1,-3,5,1,-2,3

    当m=4时,S=5+1-2+3=7
    当m=2或m=3时,S=5+1=6

    输入格式

    第一行两个数n,m(n,m<=300000)
    第二行有n个数,要求在n个数找到最大子序和

    输出格式

    一个数,数出他们的最大子序和

    样例输入

    6 4
    1 -3 5 1 -2 3

    样例输出

    7

    思路:对于区间和转化为前缀和相减的形式,即使得sum【i】 - sum【j】最大 (i > j && i - j <= m)
    贪心思想:用一个队列(数组也ok)存储可用的左节点j,开始时队列只有一个0(sum【0】 == 0),并且最左边的就是最优的节点(也就是sum【j】以递增顺序,j保存到队列中)
    当队列中最左端的节点j < i-m时出栈,对于当且节点i,也加入队列,但是要将队列中sum【j】 >= sum【i】的节点j全部出队(因为对于i后面的的节点选择最小的sum【j】,且节点越靠后越好,该节点存活越久)


    (可以数组实现)
    #include<bits/stdc++.h>
    using namespace std;
    
    deque<int>que;
    const int maxn = 3e5+5;
    int n,m;
    int sum[maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int tmp;
            scanf("%d",&tmp);
            sum[i] = sum[i-1] + tmp;
        }
        que.push_back(0);
        int ans = -INT_MAX;
        for(int i=1;i<=n;i++)
        {
            if(!que.empty() && que.front() < i-m)que.pop_front();
            ans = max(ans,sum[i] - sum[que.front()]);
            while(!que.empty() && sum[que.back()] >= sum[i])que.pop_back();
            que.push_back(i);
        }
        printf("%d
    ",ans);
    }
    View Code


  • 相关阅读:
    D语言中的Range与C#中IEnumreable的区别
    D语言中使用Curl读取网页
    在D语言中如何调用Windows中的COM控件
    D语言反射
    D语言基本类型判断 traits.d
    Struts2 XML验证器
    (十四)Struts2 验证框架
    (十三)Struts2 发送电子邮件
    (十二)Struts2 数据库访问
    (十一)Struts2 文件上传
  • 原文地址:https://www.cnblogs.com/iwannabe/p/10632900.html
Copyright © 2020-2023  润新知