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.
Start by staring at the part before the first in the permutation. For every such prefix, the is just . So in that zone, the only thing that matters is the prefix maximum.
If the prefixes before the first only care about the maximum, then putting the global maximum as early as possible is obviously good. In fact, once is already first, any extra elements before the first are suspicious: they don't improve the max anymore, but they delay making positive.
Now suppose is already in the prefix, and you have already seen all values , but not . Then the current state is: What happens if you place some element next? What if you place next instead?
That gives an exchange argument: after is already present, between the first and the first , nothing except itself should appear. Otherwise both and stay the same for one more prefix, which is just dead weight.
So an optimal order is forced into a canonical shape. Let and for the whole array. Then one optimal permutation is: with one copy of skipped in that increasing part if it was already used at the front. After that, all remaining elements are irrelevant filler: every remaining prefix contributes exactly . So compute , compute , simulate the on this short special prefix, and add .
Let for the whole multiset.
Forget the exact order for a second. Look at the prefixes before the first appears. For all of them, So in that entire initial segment, the contribution is just the prefix maximum.
That means two things:
So in some optimal permutation, a copy of is first, and then the first missing-needed value should come as soon as possible.
If (there is no in the whole array), then mex is always no matter what, so putting first makes every prefix maximum equal to , and the answer is simply Done.
Now assume , so at least one exists.
Once the first element is , every later prefix already has That part of the objective is finished. Cooked. Done. Stick a fork in it.
So from now on, the only real game is to make the mex increase as early as possible.
Suppose the current prefix already contains all values but does not contain . Then the current mex is exactly .
Now compare two choices for the next element:
If you place , then:
If you place , then:
So placing next is never worse, and is usually strictly better.
That gives a clean exchange argument:
After is already in the prefix, between the first appearance of and the first appearance of , there should be nothing except itself.
Inductively, the useful part of the permutation is forced.
An optimal permutation can be chosen as where we skip one copy of inside that increasing part if the front element already used it.
Examples:
After all values have appeared, the mex is permanently and the maximum is already permanently So every remaining element is just filler, and each remaining prefix contributes exactly
This is the whole punchline:
the answer depends only on , , and .
You do not need to sort the array or build the permutation explicitly.
We split the objective into two parts.
Because we place first, every prefix maximum is . So
Simulate only the canonical useful prefix:
Maintain a boolean array seen for values , and the current mex curMex.
Each time you add one of those special elements, update curMex and add it to the mex sum.
Let the length of this special prefix be . Then the remaining positions all contribute mex , so add
Finally,
The proof is just the two observations above glued together:
Thatβs it. No DP, no black magic, no sacrificial goats.
For each test case:
So the total complexity is per test case, and over all test cases.
Memory usage is
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
vector<char> present(n + 1, false);
int M = 0;
for (int i = 0; i < n; ++i) {
cin >> a[i];
M = max(M, a[i]);
if (a[i] <= n) present[a[i]] = true;
}
int K = 0;
while (K <= n && present[K]) ++K;
// Simulate the mex on the canonical optimal useful prefix:
// [M, 0, 1, ..., K-1], skipping one copy of M if needed.
vector<char> seen(K + 1, false);
int curMex = 0;
ll mexSum = 0;
int used = 0;
auto add = [&](int v) {
if (v <= K) seen[v] = true;
while (curMex <= K && seen[curMex]) ++curMex;
mexSum += curMex;
++used;
};
add(M);
for (int x = 0; x < K; ++x) {
if (x == M) continue;
add(x);
}
// Remaining elements are filler: max = M and mex = K forever.
mexSum += 1LL * (n - used) * K;
ll ans = 1LL * n * M + mexSum;
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
vector<char> present(n + 1, false);
int M = 0;
for (int i = 0; i < n; ++i) {
cin >> a[i];
M = max(M, a[i]);
if (a[i] <= n) present[a[i]] = true;
}
int K = 0;
while (K <= n && present[K]) ++K;
// Simulate the mex on the canonical optimal useful prefix:
// [M, 0, 1, ..., K-1], skipping one copy of M if needed.
vector<char> seen(K + 1, false);
int curMex = 0;
ll mexSum = 0;
int used = 0;
auto add = [&](int v) {
if (v <= K) seen[v] = true;
while (curMex <= K && seen[curMex]) ++curMex;
mexSum += curMex;
++used;
};
add(M);
for (int x = 0; x < K; ++x) {
if (x == M) continue;
add(x);
}
// Remaining elements are filler: max = M and mex = K forever.
mexSum += 1LL * (n - used) * K;
ll ans = 1LL * n * M + mexSum;
cout << ans << '\n';
}
}