【题目描述】:
给你一个长度为 n 的整数序列 {A1,A2,⋯,An},要求从中找出一段连续的长度不超过 m 的子序列,使得这个序列的和最大。
【输入描述】:
第一行为两个整数 n,m;
第二行为 n 个用空格分开的整数序列,每个数的绝对值都小于100。
【输出描述】:
仅一个整数,表示连续长度不超过 m 的最大子序列和。
【样例输入】:
6 4
1 -3 5 1 -2 3
【样例输出】:
7
【时间限制、数据范围及描述】:
时间:1s 空间:256M
对于 30%的数据:1<=n,m<=10,000
对于 60%的数据:1<=n,m<=1,000,000
对于100%的数据:1<=n,m<=10,000,000
【解题思路】:
维护前缀和,对于每一个前缀和S[i],寻找S[i-m]~S[i-1]中最小的那个,用单调队列维护即可
模板题请见:小雷的早餐
【AC代码】:
#include<bits/stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define Mod 19650827
using namespace std;
inline void read(int &x){
char ch=getchar(),c=ch;
x=0;
while(ch<'0' || ch>'9'){
c=ch;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
if(c=='-')x=-x;
}
int sum[10000005],q[10000005];
int head=1,tail=1;
int n,m,i,x,ans=-2147483647;
int main(){
read(n),read(m);
for(i=1;i<=n;i++){
read(x);
sum[i]=sum[i-1]+x;
}
for(i=1;i<=n;i++){
while(head<tail && i-q[head+1]>m)head++;
while(head<tail && sum[q[tail]]>sum[i])tail--;
q[++tail]=i;
ans=max(ans,sum[q[tail]]-sum[q[head+1]]);
}
printf("%d\n",ans);
return 0;
}