Problem Description
The description of this problem is very short. Now give you a string(length N), and ask you the max sum of the substring which the length can't small than M.
Input
The first line is one integer T(T≤20) indicates the number of the test cases. Then for every case, the first line is two integer N(1≤N≤1000000) and M(1≤M≤N).
Then one line contains N integer indicate the number. All the number is between -10000 and 10000.
Output
Output one line with an integer.
SampleInput
2
5 1
1 -2 -2 -2 1
5 2
1 -2 -2 -2 1
SampleOutput
1
-1
题意:T组数据,每组给n和m,n表示下面要给你的序列的长度,m表示要求的子连续序列的最短长度。接下来n个数给定序列。求一个长度大于等于m的子连续序列使得该序列所有元素之和最大。
思路:
比如第二个样例
5 2
1 -2 -2 -2 1
可以选择区间[1,2]包含1和-2,和为-1;也可以选择区间[4,5],和也为-1。
由于n有,所以的算法如果剪枝不好,比较容易TLE。
为描述方便,假设题目数据给我们的序列为数组a(下标从1-n),我们可以先预处理一个前缀和sum。
然后题目要求的就是最大的sum[r]-sum[l]:要求r–l+1 >= m,l>=1,r<=n。
这里的l的r分别表示区间左端点和右端点。我们可以从左到右遍历整个序列,由于要求的序列长度必须大于等于m,所以r要从m开始。
于是对于每一个r我们要求的是:当l满足1<=l<=r-m+1时,最小的sum[l](要sum[r]-sum[l]最大,sum[l]最小)。
那么我们只要在从左到右遍历的时候维护当前最小的sum[l]就可以了。
AC代码:562ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 typedef long long ll; 6 7 const ll INFLL = 0x7fffffffffffffffLL; 8 const int MAXN = 1000005; 9 int a[MAXN]; 10 ll sum[MAXN]; 11 12 int main() { 13 int T, n, m, i; 14 scanf("%d", &T); 15 while(T--) { 16 scanf("%d%d", &n, &m); 17 for(i = 1; i <= n; i++) { 18 scanf("%d", &a[i]); 19 sum[i] = sum[i - 1] + a[i]; 20 } 21 int r = m; 22 ll mi = 0, ans = -INFLL; 23 while(r <= n) { 24 mi = min(sum[r - m], mi); 25 ans = max(ans, sum[r] - mi); 26 r++; 27 } 28 printf("%I64d ", ans); 29 } 30 return 0; 31 }