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 */