Each minute, the followings happen in order.
洛谷的翻译没有翻译出来“in oder”。。。
翻译
这个被称为魔法蘑菇的仙境森林因其上生长的蘑菇而得名。它们可能会产生幻觉,一般应远离接近。
- 《完全不可信赖的名录记》
Marisa来到了仙境森林采摘蘑菇。
仙境森林可以用X轴上的 n n n个点来表示,编号从 1 1 1到 n n n。在Marisa开始之前,她的朋友Patchouli使用魔法探测每个点上初始的蘑菇数量,表示为 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,…,an。
Marisa可以在第 0 0 0 分钟时从森林中的任意一个点开始。每分钟,按照以下顺序发生:
- 她从点 x x x移动到点 y y y( ∣ x − y ∣ ≤ 1 |x-y|\le 1 ∣x−y∣≤1,可能有 y = x y=x y=x)。
- 她收集点 y y y上的所有蘑菇。
- 森林中的每个点都会出现一个新的蘑菇。
注意,她不能在第 0 0 0 分钟收集蘑菇。
现在,Marisa想知道在
k
k
k 分钟后她最多能采摘的蘑菇数量。
输入
每个测试用例包含多个测试案例。第一行包含一个整数 t t t( 1 ≤ t ≤ 1 0 4 1\leq t\leq 10^4 1≤t≤104)——测试用例的数量。以下是各个测试案例的描述。
每个测试案例的第一行包含两个整数 n n n 和 k k k( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1≤n≤2⋅105, 1 ≤ k ≤ 1 0 9 1\le k \le 10^9 1≤k≤109),分别代表蘑菇位置的数量和Marisa的时间。
每个测试案例的第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,…,an( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109),表示点 1 , 2 , … , n 1,2,\ldots,n 1,2,…,n上的初始蘑菇数量。
保证所有测试案例中
n
n
n 的总和不超过
2
⋅
1
0
5
2 \cdot 10^5
2⋅105。
输出
对于每个测试案例,输出Marisa在
k
k
k 分钟后能够采摘到的最多的蘑菇数量。
注意
测试案例 1:
Marisa可以从 x = 2 x=2 x=2开始。在第一分钟,她从 x = 2 x=2 x=2移动到 x = 1 x=1 x=1并采集了 5 5 5个蘑菇。蘑菇的数量变为 [ 1 , 7 , 2 , 3 , 4 ] [1,7,2,3,4] [1,7,2,3,4]。在第二分钟,她从 x = 1 x=1 x=1移动到 x = 2 x=2 x=2并又采集了 7 7 7个蘑菇。蘑菇的数量变为 [ 2 , 1 , 3 , 4 , 5 ] [2,1,3,4,5] [2,1,3,4,5]。Marisa在 2 2 2分钟后共采摘了 12 12 12个蘑菇。
可以证明,无法采摘更多的蘑菇。
测试案例 2:
这是她可能存在的一个移动路径:
2 → 3 → 2 → 1 → 2 → 3 → 4 → 5 2 \rightarrow 3 \rightarrow 2 \rightarrow 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5 2→3→2→1→2→3→4→5
可以证明,无法采摘更多的蘑菇,最多为 37 37 37个蘑菇。
思路
- 不能走“回头路”,除非走到头。
- 消耗一个时间用于移动:既可以向左或向右移动一个单位,也可以原地不动(这也是一种移动)。
- 根据 k k k 和 n n n 的数据范围,发现“有可能”需要分类讨论。
当
k
>
=
n
k~>=~n
k >= n,这个时候可以把初始时的所有蘑菇都拿走。另外我们还需要计算可以拿走多少重新生长出来的蘑菇。
我们在这里反向计算。
在这个过程中总共新产生了
n
∗
k
n~*~k
n ∗ k 个蘑菇。最终状态剩余的
n
n
n 堆蘑菇的数量是
1
1
1 ~
n
n
n 的一个排列(例如
3
,
2
,
1
,
4
,
5
,
6
,
7
,
8
3, 2, 1, 4, 5, 6, 7, 8
3,2,1,4,5,6,7,8),其和为
(
1
+
n
)
∗
n
/
2
(1~+~n)~*~n~/~2
(1 + n) ∗ n / 2。
所以拿走的蘑菇数量为:
n
∗
k
+
(
1
+
n
)
∗
n
/
2
n~*~k~+~(1~+~n)~*~n~/~2
n ∗ k + (1 + n) ∗ n / 2。
k < n k~<~n k < n 时,并不难分析,这里不再解释。
C o d e Code Code
#include <bits/stdc++.h>
#define int long long
#define sz(a) ((int)a.size())
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 2e5 + 10;
int n, k;
int a[N];
void solve() {
cin >> n >> k;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
}
cout << " ";
if (k >= n) { // n个位置能全部走完
int s = 0;
for (int i = 1; i <= n; i ++) {
s += a[i];
}
int add = n * k - (1 + n) * n / 2;
cout << s + add << "\n";
} else { // n个位置不能全部走完
int res = 0;
int add = (0 + k - 1) * k / 2;
int s = 0;
for (int r = 1; r <= n; r ++) {
s += a[r];
if (r >= k + 1) {
s -= a[r - k];
}
if (r >= k) {
res = max(res, s + add);
}
}
cout << res << "\n";
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T = 1;
cin >> T; cin.get();
while (T --) solve();
return 0;
}