根据这道题的数据规模可知,如果一直遍历相加最后肯定会TLE,所以想到前缀和。
因为需要找到两个不连续的长度为k的区间并使这两个区间的和最大,所以先根据前缀和a[]得到从1到n-k+1每k个长度区间的和。
在进行遍历,第一次编码的时候我是先找到最大的那个长度区间记为index,然后在找和index不重合的最大的区间,并将这两个区间的值相加得到最大值(有误)。但最后只过了2/3的案例,细细思考后发现,这种方法是有问题的, 因为最后的最大值未必是最大的区间的值+与之不冲突的区间最大值;很有可能是两个较大的,但是这两个都不冲突的区间相加的值。最后得到代码2,顺利AC。
tips:数组a和sum的类型都需要设为long long 否则还是只能过2/3的案例。
//出错代码,只过了2/3的案例
using namespace std;
#include<bits/stdc++.h>
const int maxn=200005;
int a[maxn],sum[maxn];
int main(){
int t,n,k;
cin>>t;
while(t--)
{
cin>>n>>k;
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]=a[i]+a[i-1];
}
long long ans=0;
int index=0;
for(int i=1;i<=n-k+1;i++)
{
sum[i]=a[i+k-1]-a[i-1];
if(sum[i]>ans)
{
ans=sum[i];
index=i;
}
}
long long ma=0;
for(int i=1;i<=n-k+1;i++)
{
if(sum[i]>ma && abs(i-index)>=k)
{
ma=sum[i];
}
}
ans+=ma;
cout<<ans<<"\n";
}
return 0;
}
AC代码:
using namespace std;
#include<bits/stdc++.h>
const int maxn=200005;
long long a[maxn],sum[maxn]; //一定要是long long 否则右1/3的测试点过不了
int main(){
int t,n,k;
cin>>t;
while(t--)
{
cin>>n>>k;
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]=a[i]+a[i-1];
}
long long max1=-1e18,max2=-1e18;
for(int i=1;i<=n-k+1;i++)
{
sum[i]=a[i+k-1]-a[i-1];
}
for(int i=1;i<=n-2*k+1;i++)
{
if(sum[i]>max1)
{
max1=sum[i];
}
if(sum[i+k]+max1>max2)
{
max2=max1+sum[i+k];
}
}
cout<<max2<<"\n";
}
return 0;
}