Description
Solution
前置知识: 差分
不懂差分的同学可以百度先进行学习。学会差分能够 实现题目中的 相邻
个石子堆数目加
,有助于我们进一步处理。
首先思考,对于每一个石子数量,如果当前的数量不是 堆石头里面最大值
,那么它一定要进行差分操作,差分到变成
但是考虑到这样后面的石头可能也会因此增加,所以 会不断改变,需要我们去维护。
此外,考虑以下数据 一开始我们不会操作
, 但是由于后面
的改变,第一个
现在已经不是
, 所以在从左到右做完一遍后,还需要在
里继续检查是否需要差分。
至于什么时候输出 ? 如果
此时无法操作,肯定输出
了。
此外,最后从头到尾检验是不是所有数字相同,如果不是就输出 ,否则就输出差分次数即可。
Code
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5 + 5;
const int mod = 998244353;
ll a[N], t[N], tmp[N];
void solve() {
int n, k; cin >> n >> k;
ll maxz = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
t[i] = a[i] - a[i - 1];
maxz = max(maxz, a[i]);
}
ll sum = 0;
int ok = 1;
ll ans = 0;
for (int i = 1; i <= n; i++) { // 第一遍差分
sum += t[i];
maxz = max(maxz, sum);
if (i <= n - k + 1) {
if (sum < maxz) {
t[i] += maxz - sum;
t[i + k] -= maxz - sum;
ans += maxz - sum;
sum += maxz - sum;
}
} else {
if (sum < maxz) { // 无法差分 不为maxz
ok = 0;
}
}
}
sum = 0;
for (int i = 1; i <= n; i++) { // 第二遍差分
sum += t[i];
maxz = max(maxz, sum);
if (i <= n - k + 1) {
if (sum < maxz) {
t[i] += maxz - sum;
t[i + k] -= maxz - sum;
ans += maxz - sum;
sum += maxz - sum;
}
} else {
if (sum < maxz) { // 无法差分 不为maxz
ok = 0;
}
}
}
sum = 0;
for (int i = 1; i <= n; i++) {
sum += t[i];
if (sum != maxz) { // 不为maxz
ok = 0;
break;
}
}
if (!ok) {
cout << -1 << '\n';
} else {
cout << ans << '\n';
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int T = 1; cin >> T;
while(T--) {
solve();
}
return 0;
}
/*
1
6 3
6 5 4 3 4 5
ans : 3
1
4 3
1 0 0 1
ans : 2
1
7 3
4 2 2 1 1 1 2
ans : 5
*/ 
京公网安备 11010502036488号