题意:
给定1到n这n个下标位置,这n个下标位置初始时分别有
a
i
a_i
ai个蘑菇。
现在marisa可以选择从这n个位置选择一个做为起始位置,允许采k次蘑菇,并每次采完蘑菇后,可以选择向左、向右或不移动。
每次采完蘑菇后,所有位置都会新增加一个蘑菇。
问marisa采k次蘑菇,最多能采多少蘑菇。
1
<
=
k
<
=
1
0
9
,
1
<
=
n
<
=
2
∗
1
0
5
1<=k<=10^9,1<=n<=2*10^5
1<=k<=109,1<=n<=2∗105
思路:
我们可以把最终采到的蘑菇分类:原来的蘑菇,以及新增的蘑菇。
当k<=n时
每个位置位置最多只走一次,因此,对于原来的蘑菇,我们只需要取数组 a a a中区间长度为k的子数组中总和最大的那个即可;
对于新增的蘑菇,每个位置都随时间积累而增加,第一个采的位置贡献0个,第二个采的位置贡献1个,… 第k个采的位置贡献k-1个,新增的蘑菇贡献了
1
+
2
+
.
.
.
+
k
−
1
1+2+...+k-1
1+2+...+k−1个。
对于原来的蘑菇和新增的蘑菇,它们各自的最优策略不冲突,我们只需要各自计算,最后相加即可。
当k>n时
对于原来的蘑菇,我们可以把它们全部取完,因此贡献了 a 1 + . . . + a n a_1+...+a_n a1+...+an个;
对于新增的蘑菇,我们反向思考,走了k步后,我们有哪些蘑菇是必定取不了、只能舍弃的?当我们走了第 k − i ( 0 < i < n ) k-i(0<i<n) k−i(0<i<n)步时,到了点 x i x_i xi,且之后都没经过点 x i x_i xi,而点 x i x_i xi还能产生 i i i个蘑菇(即marisa从第 k − i k-i k−i步走到 k k k步),这 i i i个蘑菇是marisa取不了的。换个理解,走了k步后,每个点新增的蘑菇数都为k-1,而这n个点,又分别会剩下一些取不了的点 0 , 1 , . . . , n − 1 0,1,...,n-1 0,1,...,n−1个;因此,最终marisa采到的新增蘑菇数为 n − k , n − k − 1 , . . . , n − 1 n-k,n-k-1,...,n-1 n−k,n−k−1,...,n−1。
同样的,对于原来的蘑菇和新增的蘑菇,它们各自的最优策略不冲突,我们只需要各自计算,最后相加即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 200010;
int n, k;
ll pre[maxn];
void solve() {
scanf("%d%d", &n, &k);
for (int i = 1; i <=n; ++i) {
scanf("%lld", &pre[i]);
pre[i] += pre[i-1];
}
ll res;
if (k <= n) {
res = pre[k];
for (int i = k+1; i <= n; ++i) {
res = max(res, pre[i] - pre[i-k]);
}
res += (k-1LL)*k/2;
} else {
res = pre[n] + (k-1LL + k-n)*n/2;
}
printf("%lld\n", res);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
}