zoukankan      html  css  js  c++  java
  • 【最大连续子段和】单调队列 + 前缀和优化

    题目描述

    输入一个长度为 n 的整数序列(A1,A2,……,An),从中找出一段连续的长度不超过 M 的子序列,使得这个序列的和最大。

    输入格式

    第一行两个数 n,m
    第二行由空格隔开的 n 个整数,即 A1 ~ An 。

    输出格式

    输出一个整数,即最大连续子序列之和。

    样例数据 1

    输入  [复制]

    4 2 
    -1 3 –10 20

    输出

    20

    备注

    【数据范围】

    30% 的数据:n<=3000,m<=100
    100% 的数据 1<=N,M<=1000000,-maxlongint<=ai<=maxlongint

    题目分析

     看到了要求一个区间的和,可以想到用前缀和来表示。那么以点(i)结尾的最大连续字段和就为$sum[i] - min{sum[j]} (1 <= j < i)$

    这里又出现了单调队列的形式:维护前缀和的单调递增序列,入队维护单调性,队首即为最小值,最后比较选出最大值。

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N = 1e6 + 5;
    int n, m;
    int que[N], head, tail;
    long long ans, val[N];
    
    inline int read(){
        int i = 0, f = 1; char ch = getchar();
        for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
        if(ch == '-') f = -1, ch = getchar();
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            i = (i << 3) + (i << 1) + (ch - '0');
        return i * f;
    }
    
    inline long long readL(){
        long long i = 0, f = 1; char ch = getchar();
        for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
        if(ch == '-') f = -1, ch = getchar();
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            i = (i << 3) + (i << 1) + (ch - '0');
        return i * f;
    }
    
    inline void wr(long long x){
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) wr(x / 10);
        putchar(x % 10 + '0');
    }
    
    int main(){
        n = read(), m = read();
        for(int i = 1; i <= n; i++) val[i] = readL() + val[i - 1];
        que[head = tail = 1] = 1, ans = val[1];
        for(int i = 2; i <= n; i++){
            while(head <= tail && val[que[tail]] > val[i]) tail--;
            que[++tail] = i;
            while(que[head] < i - m  && head <= tail) head++;
            ans = max(ans, val[i] - val[que[head]]);
        }
        wr(ans);
        return 0;
    }
  • 相关阅读:
    使用jquery插件validate制作的表单验证案例
    POJ2992:Divisors(求N!因子的个数,乘性函数,分解n!的质因子(算是找规律))
    HDU1695:GCD(容斥原理+欧拉函数+质因数分解)好题
    HDU4135Co-prime(容斥原理)
    HDU1796How many integers can you find(容斥原理)
    Miller-Rabin素数测试算法(POJ1811Prime Test)
    乘法逆元+模的运算规则
    因子和与因子个数 (乘性函数)
    费马小定理的证明:
    整数(质因子)分解(Pollard rho大整数分解)
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7253567.html
Copyright © 2011-2022 走看看