输入一个长度为n的整数序列,从中找出一段长度不超过m的连续子序列,使得子序列中所有数的和最大。
输入格式
第一行输入两个整数n,m。
第二行输入n个数,代表长度为n的整数序列。
同一行数之间用空格隔开。
输出格式
输出一个整数,代表该序列的最大子序和。
数据范围
1≤n,m≤3000001≤n,m≤300000
输入样例:
6 4
1 -3 5 1 -2 3

输出样例:
7

思路:用前缀和快速求出区间和;
求出线段长度为m的最大值;
线段应该维护此线段的最小值,队首为最小值,单调队列【deque】
准备放一个数,先看是否队列长m(维护)
再求出最大值ans
把当前数放到队列中

#include <bits/stdc++.h>
using namespace std;
#define fir(i,a,b) for(int i=a;i<=b;i++)
const int N=300100;
deque<long long> q;
long long n,m,l,r,s[N],a[N],ans;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    fir(i,1,n)
    {
        cin>>a[i];
        s[i]=s[i-1]+a[i];
    }
    fir(i,1,n)
    {
        while(q.size() && q.front()<i-m)
            q.pop_front();
        //如果队头已经无法满足区间长度小于m的话,那么弹出
        //队头不满足,不需要,弹出.
        ans=max(ans,s[i]-s[q.front()]);//取当前最优值
        while(q.size() && s[q.back()]>=s[i])//如果说队尾大于当前值的话.
            q.pop_back();//不需要,弹出
        q.push_back(i);//将i放入队尾.
    }
    cout<<ans<<endl;
    return 0;
}

 posted on 2019-07-31 21:30  谁是凶手1703  阅读(74)  评论(0)    收藏  举报