The grass has dried up in Farmer John's pasture due to a drought. After hours of despair and contemplation, Farmer John comes up with the brilliant idea of purchasing corn to feed his precious cows.
FJ’s NN cows (1≤N≤1051≤N≤105) are arranged in a line such that the iith cow in line has a hunger level of hihi (0≤hi≤1090≤hi≤109). As cows are social animals and insist on eating together, the only way FJ can decrease the hunger levels of his cows is to select two adjacent cows ii and i+1i+1 and feed each of them a bag of corn, causing each of their hunger levels to decrease by one.
FJ wants to feed his cows until all of them have the same non-negative hunger level. Please help FJ determine the minimum number of bags of corn he needs to feed his cows to make this the case, or print −1−1 if it is impossible.
Each input consists of several independent test cases, all of which need to be solved correctly to solve the entire input case. The first line contains TT (1≤T≤1001≤T≤100), giving the number of test cases to be solved. The TT test cases follow, each described by a pair of lines. The first line of each pair contains NN, and the second contains h1,h2,…,hNh1,h2,…,hN. It is guaranteed that the sum of NN over all test cases is at most 105105. Values of NN might differ in each test case.
Please write TT lines of output, one for each test case.
Note that the large size of integers involved in this problem may require the use of 64-bit integer data types (e.g., a "long long" in C/C++).
5 3 8 10 5 6 4 6 4 4 6 4 3 0 1 0 2 1 2 3 10 9 9
14 16 -1 -1 -1
For the first test case, give two bags of corn to both cows 22 and 33, then give five bags of corn to both cows 11 and 22, resulting in each cow having a hunger level of 33.
For the second test case, give two bags to both cows 11 and 22, two bags to both cows 22 and 33, two bags to both cows 44 and 55, and two bags to both cows 55 and 66, resulting in each cow having a hunger level of 22.
For the remaining test cases, it is impossible to make the hunger levels of the cows equal.
Additionally, NN is always even in inputs 3-5 and 9-11, and NN is always odd in inputs 6-8 and 12-14.
Problem credits: Arpan Banerjee
[/hide]
(Analysis by Arpan Banerjee, Benjamin Qi)
Define an operation on (i,i+1)(i,i+1) as the act of decreasing both hihi and hi+1hi+1 by one. Also define ff to be the final hunger value.
Half Credit:
For inputs 1-8, it suffices to try all possible values of ff from 00 to min(hi)min(hi) and see if they result in valid solutions. This can be done by sweeping left to right across hh and remedying instances where hihi is greater than ff by doing operations on (i,i+1)(i,i+1) until one of hihi or hi+1hi+1 equals ff. If there is a solution, this method must lead to it, because doing operations on (i,i+1)(i,i+1) is the only way to make hihi equal ff assuming no more operations on (i−1,i)(i−1,i) are allowed.
This solution runs in O(Nmax(hi))O(Nmax(hi)) time.
Arpan's code:
#include<bits/stdc++.h> #define int long long #define nl "\n" using namespace std; int n; const int inf = 1e18; int cost(vector<int> h, int f){ int o = 0; for (int i = 0; i < n - 1; i++){ if (h[i] > f){ int sub = min(h[i], h[i + 1]) - f; h[i] -= sub, h[i + 1] -= sub; o += sub * 2; } } for (int i = 0; i < n - 1; i++) if (h[i] != h[i + 1]) return inf; return o; } int exe(){ cin >> n; vector<int> h(n); int mn = inf, ans = inf; for (int& i : h) cin >> i, mn = min(mn, i); for (int f = 0; f <= mn; f++) ans = min(ans, cost(h, f)); return (ans == inf ? -1 : ans); } signed main(){ cin.tie(0)->sync_with_stdio(0); cin.exceptions(ios_base::failbit); int t; cin >> t; while (t--) cout << exe() << nl; }
(Almost) Full Solution:
Consider any ii such that hi−1<hihi−1<hi. If i=Ni=N, then there is no solution because no operation can bring hNhN closer to hN−1hN−1. Otherwise, the only way to make hihi equal to hi−1hi−1 is to do at least hi−hi−1hi−hi−1 operations on (i,i+1)(i,i+1). Similar reasoning applies when hi−1>hihi−1>hi (there is no solution if i=2i=2, otherwise at least hi−1−hihi−1−hi operations must be performed on (i−2,i−1)(i−2,i−1)).
One approach is to repeatedly find the leftmost pair (i−1,i)(i−1,i) such that hi−1≠hihi−1≠hi and perform the appropriate number of operations to make hi−1=hihi−1=hi. It can be proven that this terminates in O(N3)O(N3) time, and is enough to solve all but the last input.
Ben's code:
#include <bits/stdc++.h> using namespace std; using i64 = int64_t; i64 solve(vector<i64> h){ const int N = (int)h.size(); i64 ans = 0; auto operations = [&h,&ans](int idx, i64 num_op) { assert(num_op >= 0); h.at(idx) -= num_op; h.at(idx+1) -= num_op; ans += 2*num_op; }; bool flag = true; while (flag) { flag = false; for (int i = 1; i < N; ++i) if (h[i-1] != h[i]) { flag = true; if (h[i-1] < h[i]) { if (i == N-1) return -1; operations(i,h[i]-h[i-1]); } else { if (i == 1) return -1; operations(i-2,h[i-1]-h[i]); } break; } } // now h is all equal if (h[0] < 0) return -1; return ans; } int main() { int t; cin >> t; while (t--) { int N; cin >> N; vector<i64> H(N); for (auto& i: H) cin >> i; cout << solve(H) << "\n"; } }
Full Solution 1:
For a faster solution, let's start by moving left to right across hh and applying the necessary number of operations to (i,i+1)(i,i+1) to make hihi equal to hi−1hi−1 whenever we find ii such that hi>hi−1hi>hi−1. After doing a pass through the array with this procedure, either hN>hN−1hN>hN−1 (in which case there is no solution), or hh will be non-increasing (hi≤hi−1hi≤hi−1 for all 2≤i≤N2≤i≤N).
In the latter case, let's reverse hh. Now hh will be non-decreasing (hi≥hi−1hi≥hi−1 for all 2≤i≤N2≤i≤N). After one more pass with the above procedure, all elements of hh will be equal except possibly hNhN. If hN>hN−1hN>hN−1, then there is no solution. Otherwise, all elements of hh are equal, and it remains to verify whether these elements are non-negative.
This solution takes O(N)O(N) time.
Arpan's code:
#include<bits/stdc++.h> #define int long long #define nl "\n" using namespace std; int exe(){ int ans = 0, n; cin >> n; vector<int> h(n); for (int& i : h) cin >> i; if (n == 1) return 0; for (int j : {1, 2}){ for (int i = 1; i < n - 1; i++){ if (h[i] > h[i - 1]){ int dif = h[i] - h[i - 1]; ans += 2 * dif, h[i + 1] -= dif, h[i] = h[i - 1]; } } if (h[n - 1] > h[n - 2]) return -1; // now h is non-increasing reverse(h.begin(), h.end()); // now h is non-decreasing } // now h is all equal return h[0] < 0 ? -1 : ans; } signed main(){ cin.tie(0)->sync_with_stdio(0); cin.exceptions(ios_base::failbit); int t; cin >> t; while (t--) cout << exe() << nl; }
Full Solution 2:
Let oioi be the total number of operations FJ performs on (i,i+1)(i,i+1) for each 1≤i<N1≤i<N. The goal is to find the maximum ff such that there exists a solution to the following system of equations. Firstly, the final hunger value and the number of operations performed at every pair of indices must be non-negative:
Also,
The first solution in the analysis can be interpreted as trying all possible values of ff from 00 to min(hi)min(hi), determining o1,o2,…,oN−1o1,o2,…,oN−1 in that order, and checking whether all of them are non-negative. For a faster solution, let’s rewrite the system of equations in the following form.
Observe that if NN is odd, the last equation uniquely determines ff, so we can simply plug this value of ff into the brute force solution.
If NN is even, then if there exists some ff such that this system of equations, then f′=0f′=0 will as well. Let o′1,o′2,…,o′N−1o1′,o2′,…,oN−1′ be the resulting numbers of operations. To find the maximum ff, observe from the above equations that increasing f′f′ will decrease o′1,o′3,…,o′N−1o1′,o3′,…,oN−1′, while o′2,o′4,…,o′N−2o2′,o4′,…,oN−2′ remain constant. Thus, we may take f=min(o′1,o′3,…,o′N−1)f=min(o1′,o3′,…,oN−1′).
Ben's code:
#include <bits/stdc++.h> using namespace std; using i64 = int64_t; i64 solve(const vector<i64>& H) { const int N = (int)H.size(); i64 f = 0; for (int i = 0; i < N; ++i) f += (i%2 == 0 ? 1 : -1)*H[i]; if (N%2 == 0) { if (f != 0) return -1; } else { if (f < 0) return -1; } i64 last_o = 0; vector<i64> o(N-1); for (int i = 0; i+1 < N; ++i) { last_o = o[i] = H[i]-f-last_o; if (o[i] < 0) return -1; } if (N%2 == 0) { i64 mn = o[0]; for (int i = 0; i < N; i += 2) mn = min(mn,o[i]); for (int i = 0; i < N; i += 2) o[i] -= mn; } i64 sum_o = 0; for (i64 i: o) sum_o += i; return 2*sum_o; } int main() { int t; cin >> t; while (t--) { int N; cin >> N; vector<i64> H(N); for (auto& i: H) cin >> i; cout << solve(H) << "\n"; } }
[/hide]
翰林课程体验,退费流程快速投诉邮箱: yuxi@linstitute.net 沪ICP备2023009024号-1