1013 数学考试 前缀和

链接:https://ac.nowcoder.com/acm/contest/24213/1013
来源:牛客网

题目描述

今天qwb要参加一个数学考试,这套试卷一共有n道题,每道题qwb能获得的分数为ai,qwb并不打算把这些题全做完,
他想选总共2k道题来做,并且期望他能获得的分数尽可能的大,他准备选2个不连续的长度为k的区间,
即[L,L+1,L+2,....,L+k-1],[R,R+1,R+2,...,R+k-1](R >= L+k)。

输入描述:

第一行一个整数T(T<=10),代表有T组数据
接下来一行两个整数n,k,(2<=n<=200,000),(1<=k,2k <= n)
接下来一行n个整数a1,a2,...,an,(-100,000<=ai<=100,000)

输出描述:

输出一个整数,qwb能获得的最大分数
示例1

输入

复制
2
6 3
1 1 1 1 1 1
8 2
-1 0 2 -1 -1 2 3 -1

输出

复制
6
7

分析

求出一段区间的两段相加后 最大的两个子区间

只要前缀和预处理,遍历的时候,保留i左边的最大k长的最大子区间,sum[i+k] - sum[i] 来得到右边的k长区间,用ans 对每个i 取最大值就可以了

易错点:

a[i] 是有可能是负的,所以mx 初始化成负无穷

 

//-------------------------代码----------------------------

#define int LL
const int N = 2e5+10;
int n,k;
int a[N],sum[N],b[N];
void solve()
{
memset(sum,0,sizeof sum);
cin>>n>>k;
fo(i,1,n) {
cin>>a[i];
sum[i] =sum[i-1] + a[i];
}

int mx = -0x3f3f3f3f3f3f3f3f;
int ans = -0x3f3f3f3f3f3f3f3f;
fo(i,k,n-k) {
b[i] = max(mx,sum[i] - sum[i-k]);
// dbb(sum[i] - sum[i-k],i-k,i);
mx = max(mx,b[i]);
int tt = sum[i+k] - sum[i];
ans = max(ans,tt + mx);
}
cout<<ans<<endl;
}

signed main(){
clapping();TLE;

int t;cin>>t;while(t -- )
solve();
// {solve(); }
return 0;
}

/*样例区


*/

//------------------------------------------------------------

posted @ 2022-07-06 15:55  er007  阅读(27)  评论(0)    收藏  举报