最大子序和

题目链接:https://www.acwing.com/problem/content/137/

首先我们可以枚举右端点i,当i固定时,问题就变为:找到一个左端点j,其中j在[i-m,i-1],并且s[j]最小。

我们可以假设任意两个位置j和k,如果k<j<i并且s[k]>=s[j],那么对于所有>=i的右端点,k永远不会成

为最好的选择。所有可能成为最好选择的策略是:下标位置递增,对应的前缀和S的值也递增

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
int a[300005],q[300005],sum[300005];
int main()
{
    int i,j,m,n,ans,w,k,l,r;
    while(~scanf("%d %d",&n,&m))
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        l=r=1;
        q[1]=0;
        ans=-9999999;
        for(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--;
            q[++r]=i;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2019-08-02 23:06  ~zcb  阅读(181)  评论(0编辑  收藏  举报