CHOJ1201最大子序和

1201 最大子序和 0x10「基本数据结构」例题

描述

输入一个长度为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[],枚举右端点,典型单调队列题。。。
#include<bits/stdc++.h>
using namespace std;
#define why 300005
int q[why],n,m,ans,sum[why]; 
inline int redn()
{
    int ret=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        f=(ch!='-')?f:-f;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        ret=ret*10+ch-'0';
        ch=getchar();
    }
    return f>0?ret:-ret;
}
int main()
{
    int l=1,r=1,_1; 
    q[1]=0;
    //初始化
    n=redn();
    m=redn();
    for(int i=1;i<=n;++i)
    {
        _1=redn();
        sum[i]=sum[i-1]+_1;
    }
    //读入 
    for(int i=1;i<=n;++i)
    {
        while(l<=r&&q[l]<i-m)++l;//删除"过期"队首
        ans=max(ans,sum[i]-sum[q[l]]);//更新答案
        while(l<=r&&sum[q[r]]>=sum[i])--r;//删除不优秀的决策:(sum[i]-sum[q[r]])都<0了,何必留着
        q[++r]=i;//i也是个好决策,可以更新后面的,所以入队
    }
    printf("%d",ans);
    return 0;
}

 



posted @ 2019-06-11 15:38  OI入梦  阅读(230)  评论(0编辑  收藏  举报