【k长度最大连续子序和】 最大子序和

传送门

题意

长度为\(n\)的整数序列,找出一段长度不超过\(m\)的和最大的连续子序列

数据范围

\(1\leq n \leq 3·10^{5}\)

题解

  • 预处理前缀和,贪心法,假如右端点\(i\)固定,找到一个左端点\(j \in [i-m,i-1]\)\(s_{j}\)要尽量的小,

  • 为了使得区间和最大,\(j\)的取值,是一个区间,我们只要这个区间的最值。区间最值,就可以通过单调队列处理。

  • 如果有一个位置\(k\)\(k<j<i\).而且\(sum_{k}\geq sum_{j}\),那么\(sum_{i}-sum_{k} \leq sum_{i} -sum_{j}\)

    • 也就是说\(j\)更靠近 \(i\) ,不易超过限制\(m\),并且答案更优,那么\(k\)是没有用了。所以每次更新的时候先把越界的队头去除,剩下的显然就是最优解

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
const int N=3e5+10;
int s[N];
int n,m;
int ans=-1e9;

deque<int>q;

int main()
{
    scanf("%d%d",&n,&m);

    rep(i,1,n+1)
    {
        scanf("%d",&s[i]);
        s[i] += s[i-1];
    }
    q.push_back(0);
    rep(i,1,n+1)
    {
        while(q.size() && i-m>q.front()) q.pop_front();
        ans=max(ans,s[i]-s[q.front()]);
        while(q.size() && s[q.back()]>=s[i]) q.pop_back();
        q.push_back(i);
    }
    printf("%d",ans);
}

posted @ 2020-09-22 11:54  Hyx'  阅读(319)  评论(0编辑  收藏  举报