数学考试

传送门

题目大意

给定一段长度为n序列,选择两个不连续的长度均为k的区间,[L,L+1,L+2,....,L+k-1],[R,R+1,R+2,...,R+k-1](R >= L+k),求这两个区间和的最大值。

思路

求区间和肯定可以想到用前缀和了,但是怎么找这两个区间呢?我一开始想的是把n-k+1个子区间的和都求出来然后用二重循环去找,但是发现肯定超时,所以要改变一下思路。可以把前i个数中长度为k的区间的和的最大值求出来,然后跟以i+1为起点的长度为k的区间和相加,随着i的增大不断更新最大值,这样子就只需要一重循环就可得出答案。这么做为什么可以呢?为了方便说明,把要找的两个区间一个叫做左区间,一个叫做右区间。在循环过程中,我们其实遍历了所有的右区间,然后让右区间都与其左边的最大的长度为k子区间相加,很显然得到的结果自然就是我们想要的答案。还有一点要说明,初始值ans一定要赋值一个很小的数,我做的时候连续WA了好几发在第5个测试点,后来去看别人的提交才改过的。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N],b[N];
int main(){
	int t,n,k;
	scanf("%d",&t);
	while (t--){
		scanf("%d %d",&n,&k);
		memset(b,0,sizeof(b));
		for (int i=1;i<=n;i++){
			scanf("%lld",&a[i]);
			b[i]=b[i-1]+a[i];
		}
		ll ans=-0x3f3f3f3f3f3f,pre=-0x3f3f3f3f3f3f;
		for (int i=k;i<=n-k;i++){
			pre=max(pre,b[i]-b[i-k]);   //维护前i个数中长度为k的区间的最大值
			ans=max(ans,pre+b[i+k]-b[i]);
		} 
		printf("%lld\n",ans);
	}
	return 0;
} 
posted @ 2020-09-26 23:11  一段时光  阅读(162)  评论(0)    收藏  举报