Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
That weird swap sequence is just reversing an odd-length subarray centered at . Ask yourself: after such a reversal, what property of an element’s position never changes?
If an element starts on an odd index, it always stays on an odd index; same for even. So the whole problem secretly splits into two disjoint worlds: odd positions and even positions. Nice. Much less bullshit to think about.
Suppose an element is currently at position , and you want it to appear at index . When is that possible in one operation? If , reverse the segment . Since its length is odd, that element lands exactly at .
So for one parity class, only the number of operations whose has that parity matters. With those operations, you can choose to mark exactly distinct elements of that parity for any with if ; after that, extra operations can just re-mark an already marked element. If , then .
Take values on odd indices and even indices separately, sort each in descending order, and compute prefix sums. For a parity with , contribution is . Otherwise, its best marked-sum contribution is Then the answer is That’s the whole trick.
In one operation, you choose a center and length , then swap This is exactly reversing the subarray Its length is so it is always odd.
That odd length is the first big clue.
If an element is at position inside the reversed segment, after reversal it moves to Since is even, So an element on an odd index can never move to an even index, and vice versa.
That means the array splits into two independent pools:
A mark at an odd index can only ever mark an odd-position element. Same for even.
This is the real aha.
Suppose some element is currently at position , and the current operation wants to mark index . If then reverse the odd-length segment Its center is , an integer because the parities match. After this reversal, the element from moves exactly to .
So before any operation at index , you may choose any currently unmarked element of the same parity and put it at in one operation.
That absolutely kills the hard part.
Let:
Now focus on just one parity class, say odd. Suppose there are odd-index elements total, and there are odd operations.
What sets of odd elements can we end up marking?
So for that parity, we may choose exactly any number of distinct marked elements if , and if .
Therefore, to maximize the total sum of marked elements for that parity, we just want the best possible sum of elements from that pool.
And, well, duh: that means the top values after sorting in descending order.
Let be the values from one parity class, sorted descending: Define prefix sums
Then the best marked-sum contribution of that parity is:
Notice why this is not always just “take as many as possible”: if values become negative, adding more marked elements can make the marked sum worse. Since repeated marks are allowed, you can stop introducing new elements and just re-mark an old one.
That is exactly why sample cases with lots of negative numbers don’t simply take elements.
Let
Then
Because marked and unmarked partition the array.
We prove the algorithm is correct.
An element never changes the parity of its index.
Proof. Under a reversal centered at , position maps to , which has the same parity as . ∎
Before an operation marking index , any element currently at a position with can be moved to in one operation.
Proof. Reverse the segment . Its length is odd, and reversal sends to . ∎
For one parity class with operations and elements, any number of distinct marked elements is achievable.
Proof. On the first operations of that parity, use Lemma 2 to move chosen unmarked elements one by one to the queried indices and mark them. On later operations of that parity, move any already marked element there again. ∎
For fixed , the maximum possible sum of marked elements from one parity class is the sum of its largest values.
Proof. This is just sorting 101. Any other -element subset has sum no larger. ∎
The algorithm outputs the minimum possible sum of unmarked elements.
Proof. By Lemma 1, odd and even classes are independent. By Lemma 3, for each parity we may choose any allowed number of distinct marked elements. By Lemma 4, the best choice for that is the top values. So the optimal marked sum for each parity is exactly the maximum allowed prefix sum. Summing both parities gives the maximum total marked sum, hence subtracting from gives the minimum unmarked sum. ∎
For each test case, we sort the odd and even lists. So the complexity is which is easily fine under the given limits.
Memory usage is
Pretty clean. The whole trick is realizing the operation looks scary, but parity turns it into a glorified sorting/prefix-sum problem.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static ll bestMarked(vector<ll> v, int k) {
if (k == 0 || v.empty()) return 0;
sort(v.begin(), v.end(), greater<ll>());
ll pref = 0;
ll best = LLONG_MIN;
int lim = min<int>(k, (int)v.size());
for (int i = 0; i < lim; ++i) {
pref += v[i];
best = max(best, pref);
}
return best;
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<ll> odd, even;
odd.reserve((n + 1) / 2);
even.reserve(n / 2);
ll total = 0;
for (int i = 1; i <= n; ++i) {
ll x;
cin >> x;
total += x;
if (i & 1) odd.push_back(x);
else even.push_back(x);
}
int kOdd = 0, kEven = 0;
for (int i = 0; i < m; ++i) {
int x;
cin >> x;
if (x & 1) ++kOdd;
else ++kEven;
}
ll markOdd = bestMarked(odd, kOdd);
ll markEven = bestMarked(even, kEven);
cout << total - markOdd - markEven << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static ll bestMarked(vector<ll> v, int k) {
if (k == 0 || v.empty()) return 0;
sort(v.begin(), v.end(), greater<ll>());
ll pref = 0;
ll best = LLONG_MIN;
int lim = min<int>(k, (int)v.size());
for (int i = 0; i < lim; ++i) {
pref += v[i];
best = max(best, pref);
}
return best;
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<ll> odd, even;
odd.reserve((n + 1) / 2);
even.reserve(n / 2);
ll total = 0;
for (int i = 1; i <= n; ++i) {
ll x;
cin >> x;
total += x;
if (i & 1) odd.push_back(x);
else even.push_back(x);
}
int kOdd = 0, kEven = 0;
for (int i = 0; i < m; ++i) {
int x;
cin >> x;
if (x & 1) ++kOdd;
else ++kEven;
}
ll markOdd = bestMarked(odd, kOdd);
ll markEven = bestMarked(even, kEven);
cout << total - markOdd - markEven << '\n';
}
return 0;
}