FOJ-2013 A Short Problem (前缀和)

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

 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\n", ans);
29     }
30     return 0;
31 }
View Code

 

转载于:https://www.cnblogs.com/sandychn/p/9482129.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值