[NC15553] 数学考试
1 2 3
| 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld
|
题目描述
今天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)。
输入描述
1 2 3
| 第一行一个整数T(T<=10),代表有T组数据 接下来一行两个整数n,k,(2<=n<=200,000),(1<=k,2k<=n) 接下来一行n个整数a1,a2,...,an,(-100,000<=ai<=100,000)
|
输出描述
输入
1 2 3 4 5
| 2 6 3 1 1 1 1 1 1 8 2 -1 0 2 -1 -1 2 3 -1
|
输出
题解
题目解析
这道题是一个区间dp+前缀和的题目,按理说应该挺简单的= =.但是我还是卡了好长时间.
这道题的做法是 $O(n)$ 方法.用一个res1变量始终维护全部左侧长度为k的区间最大值.然后依次一个一个遍历右侧所有长度为k的区间就好了.因为我们已经维护左侧所有长度为k的最大值了,res2就可以维护以移动指针i到i+k区间与i左边所有区间的最大值就好了,然后i从k->n-k遍历一遍就得到答案了.
AC代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <iostream> #include <cmath> using namespace std; typedef long long ll; const int MAXN = 200010;
ll dp[MAXN],sum[MAXN],res1,res2; int T,n,k,temp;
signed main(){ cin >> T; while(T--){ cin >> n >> k; res1 = res2 = -1e18; for(int i=1;i<=n;i++){ cin >> temp; sum[i] = sum[i-1] + temp; } for(int i=k;i<=n-k;i++){ res1 = max(res1,sum[i]-sum[i-k]); res2 = max(res2,res1+sum[i+k]-sum[i]); } cout << res2 << endl; } return 0; }
|