题意
给出n个数,从中选出长度不超过m的连续子序列,使得和最大。
分析
这道题就不能有传统的递推。
看到连续序列的和,应该想到用前缀和维护,对于某个数,只要在ta前面 m + 1 m+1 m+1 范围内找到前缀和值最小的就行。所以维护一个单调上升的前缀和值队列,碰到一个打擂台就行,注意一开始应该把0入队。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
deque<int> q;
int n,m,a[300010],ans,s[300010];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
s[i]=s[i-1]+a[i];
}
ans=-0x7fffffff;
q.push_back(0);
for(int i=1;i<=n;i++)
{
while(!q.empty()&&i-q.front()>m) q.pop_front();
while(!q.empty()&&s[i]<=s[q.back()]) q.pop_back();
q.push_back(i);
ans=max(ans,s[i]-s[q.front()]);
}
cout<<ans;
return 0;
}