【题目描述】
输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。
例如整数序列{1,-3,5,1,-2,3},当m=4时,S=5+1-2+3=7;当m=2时,S=5+1=6。
【输入】
第一行两个数n,m(n,m<=300000)。
第二行有n个数,要求在n个数找到最大子序和。
【输出】
一个数,表示它们的最大子序和。
思路:前缀和+单调序列(好像还不是特别懂,懂了但又没懂,就直接放代码了)
#include<bits/stdc++.h>
using namespace std;
const int N=300010;
int s[N];
int main()
{
int m,n,a;
cin>>n>>m;
//前缀和
for(int i=1;i<=n;i++)
{
cin>>a;
s[i]+=s[i-1]+a;
}
//动态队列(单调队列)存储前缀和的下标位置
deque<int>q;
q[0]=0;
int ans=s[1];
for(int i=1;i<=n;i++)
{
//q不为空且队首存的位置超过小框即小于(i-m),队首出列
if(!q.empty()&&q.front()<i-m)
q.pop_front();
//前缀和相减,每次减去最小的前缀和即为连续子序列的极大值
ans=max(ans,s[i]-s[q.front()]);
//如果不为空且当前的前缀和小于队尾,队尾剔除,插入当前下标
while(!q.empty()&&s[i]<=s[q.back()])
q.pop_back();
q.push_back(i);
}
cout<<ans;
return 0;
}