题目描述:
小牛做题,给出长度为n的数组,数组中ai表示解决题目i可以获得的分数,小牛会在这n个题中选择2k个题目来做,每次解决连续的k个题目,求能获得的最大分数。
解题思路:
因为每次的区间都是一定的,可以用a[i]+a[i-1]求该数组的前缀和数组,从第k个数开始遍历整个数组,第一次求出区间为k最大的分数,第二次也从k开始遍历,求出第二大的区间,讲两个区间的值相加得到答案。
然而这种方法有一定的缺陷,当两个区间相连时,无法取到最大的分数如:
-10000,-10000,1,1,3, 10 ,2,1
如果按照上面的方法遍历,第一次得到的数据为15,第二次得到的为-20001,和为-19986,然而正确的答案显然是18。为了解决这种情况我们再从2k开始遍历,每次取连续2k区间分数的和,再和之前求得的区间和比较大小取最大值为最终的答案。
注意事项:
该题每个数据都较小,但是因为该题使用了前缀和算法,所以我们使用记录答案的数据和记录前缀和的数组都使用long long类型
代码如下:
#include<iostream> using namespace std; long long int arry[200010] = {0}; int main() { int n; cin >> n; while (n--) { int m, k; cin >> m >> k; for (int i = 1; i <= m; i++) { int temp; cin >> temp; arry[i] = temp + arry[i - 1]; } long long int ans = -1e18; long long int ans2 = -1e18; int temp2=0; for (int i = k; i <= m; i++) { if (arry[i] - arry[i - k] > ans) { ans = (arry[i] - arry[i - k]); temp2 = i; } } for (int i = k; i <= m; i++) { if (i <= temp2 - k || i >= temp2+k) { if (arry[i] - arry[i - k] > ans2) { ans2 = arry[i] - arry[i - k]; } } } ans += ans2; for (int i = 2 * k; i <= m; i++) { if (arry[i] - arry[i - 2 * k] > ans) { ans = arry[i] - arry[i - 2 * k]; } } cout << ans << endl; } return 0; }