Розбір
Problem Author: | Maksym Shvedchenko |
Prepared by: | Illia Fursov, Illia Shevchenko |
Editorial by: | Illia Fursov |
Group 1: .
Let's take a look at both cases ( and ):
: the only way to perform operations in this case is to take subarrays and and to remove both elements from their subarrays. This way, both parts become empty, their sums become 's and the difference between them is always ;
: since two elements from the initial array are removed, one element remains. This element belongs to one of the subarrays, and the other subarray is empty. If this one remaining elements is , then the answer is . Actually, any of three elements of the array can be such . Here is how:
-> , -> ,
-> , -> ,
-> , -> ,
Thus, the answer for this case is .
Time and memory complexity: .
Group 2: all elements of the array are equal.
In this group, we can notice that, in case of choosing as a dividing index and removing any element from both resulting subarrays, the sums of parts are guaranteed to be and and the difference between them is .
and are constants, thus our task now is to choose such that reaches its maximum value (since the larger are absolute values of the multiples — the larger is the absolute value of their product).
, thus the value of varies from to . The maximum absolute value of a number from this range is , thus the answer for the group is .
Time and memory complexity: or (we do not need to read the whole array, just the first number is enough).
Group 3: all elements of the array are positive.
In this group, the most optimal way is to choose either or as a dividing index.
Knowing that, in this group it is enough to check both first and last elements of the array as the single element of a subarray and check all other elements as if they were the one removed from the other subarray.
Time and memory complexity: .
Group 4: the array is non-decreasing.
If there are numbers of only one sign (including zeros as the numbers of the same sign as non-zero numbers) — then the solution is the same as for the previous group.
Otherwise, let's think about the case when there are no zeros in the array. The most optimal way to divide the array here is actually to take all the negative elements to one part and to remove the largest one of them and to take all the positive elements to another part and to remove the smallest one of them.
If there is one zero in the array — then we can try to consider it as a negative and as a positive number (in both cases it will be the one element removed from its part).
If there are two or more zeros in the array — then we can distribute them in any way such that at least one of them is in the first part and at least one is in the second part.
Group 5: .
To solve this group, we can, in fact, just do what is said in the statement: iterate through all the possible 's (from to ) to divide the initial array, then try all the combinations of and such that and and update the answer with the difference we get with these values. To keep the sum of elements of both subarrays before deleting -th and -th elements, we can store the current , the of the whole array, update the when moving and take . To update the answer, we can just remove and from sums of their subarrays (take the value ).
Time complexity:
Memory complexity:
Group 6: .
The best answer for some is obtained by removing either maximum or minimum elements from both subarrays.
Thus, the optimization we can do for the solution from the previous group, is to only update the answer using and vice versa . To keep such indices, we can recalculate them for every iteration of in linear time. Updating answer is just handling cases with formulas, which is .
Time complexity:
Memory complexity:
Group 7: no additional constraints.
The solution for this group is the same as for the previous one, but we can update and indices while moving through the 's and take the same values for the right part using multiset or suffix minimums and maximums.
Full solution with time complexity (C++):
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 12; const int inf = 1e9 + 7; int n; int a[N]; int L_mn = inf, L_mx = -inf; int R_mn[N], R_mx[N]; ll sum = 0, L_sum = 0; ll ans = 0; int main() { cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; sum += a[i]; } R_mn[n - 1] = R_mx[n - 1] = a[n - 1]; for (int i = n - 2; i >= 0; i--) { R_mn[i] = min(R_mn[i + 1], a[i]); R_mx[i] = max(R_mx[i + 1], a[i]); } for (int i = 0; i < n - 1; i++) { L_sum += a[i]; L_mn = min(L_mn, a[i]); L_mx = max(L_mx, a[i]); ans = max(ans, abs((L_sum - L_mn) - (sum - L_sum - R_mx[i + 1]))); ans = max(ans, abs((L_sum - L_mx) - (sum - L_sum - R_mn[i + 1]))); } cout << ans << endl; }
Time complexity: or
Memory complexity: