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.
Forget positions for a second. For one operation, the only things that matter are the counts of each value and the MEX of the whole array.
Let be the current whole-array MEX. If you remove one copy of value , when does the MEX change from ? Only when and that copy was the only copy of .
So after one operation: every value with count stays as , and every other element becomes . Big values, duplicates, random junk: all of it gets nuked into .
Look at the first duplicated value , if it exists. After one more operation, the array becomes a clean shape: one copy of and all remaining elements equal to .
That clean shape has period : it flips between filling the rest with and filling the rest with . If there was no duplicated value below the original MEX, use and the clean shape starts immediately after the first operation.
The operation looks index-based, but that is mostly bait. The value of an element after an operation depends on only two things:
The fact that everything updates simultaneously matters. We always reason from the old counts, not from half-updated garbage.
One Operation Exactly
Let be the MEX of the current array. That means:
Now take an element with value and remove it temporarily.
If and appeared exactly once, then removing it makes missing. All smaller values still exist, so the MEX of the remaining array is .
Otherwise, removing this element does not break the presence of all values . Since was already missing, it is still missing. So the MEX is still .
So the new value is:
That's the whole problem. Seriously. The rest is just not messing up the parity.
Therefore, after the first operation:
The sum after one operation is easy:
If , we are done.
What Happens After That?
Now find the first duplicated value below the original MEX:
There are two cases.
Case 1: A duplicated small value exists
Suppose this first duplicated value is .
After the first operation, disappears, because duplicated values below do not survive. Every value below was not duplicated, because was the first duplicated one, so are still present exactly once.
So the new MEX becomes .
After one more operation, only those unique values stay, and every other element becomes .
So at operation , the array has this clean form:
Call this the low state.
Case 2: No duplicated small value exists
Then all values occur exactly once.
After the first operation, those values stay, and every other element becomes :
So we get the same clean form immediately, with .
If , this is just the permutation , whose MEX behavior is fixed forever. The answer is:
The Period-2 Cycle
For , the clean low state is:
Its MEX is , because through are present.
Apply the operation:
So it becomes the high state:
Now the MEX is , because is missing. Apply the operation again, and all the values become . Back to the low state.
So after reaching the clean form, the array alternates forever. Very considerate of it, honestly.
The low-state sum is:
The high-state sum is:
Putting It Together
Compute the initial MEX and the first duplicated value below it.
The runtime is per test case, and the total is bounded, so this cruises comfortably.
#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;
ll k;
cin >> n >> k;
vector<int> cnt(n + 1, 0);
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
++cnt[x];
}
int mex = 0;
while (mex <= n && cnt[mex] > 0) ++mex;
ll uniqueCnt = 0, uniqueSum = 0;
int firstDup = -1;
for (int x = 0; x < mex; ++x) {
if (cnt[x] == 1) {
++uniqueCnt;
uniqueSum += x;
} else if (firstDup == -1) {
firstDup = x;
}
}
ll afterOne = uniqueSum + 1LL * mex * (n - uniqueCnt);
if (k == 1) {
cout << afterOne << '\n';
continue;
}
if (firstDup == -1) {
int p = mex;
if (p >= n - 1) {
cout << 1LL * n * (n - 1) / 2 << '\n';
continue;
}
ll base = 1LL * p * (p - 1) / 2;
ll low = base + 1LL * p * (n - p);
ll high = base + 1LL * (p + 1) * (n - p);
cout << (((k - 1) % 2 == 0) ? low : high) << '\n';
} else {
int p = firstDup;
ll base = 1LL * p * (p - 1) / 2;
ll low = base + 1LL * p * (n - p);
ll high = base + 1LL * (p + 1) * (n - p);
cout << (((k - 2) % 2 == 0) ? low : high) << '\n';
}
}
return 0;
}#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;
ll k;
cin >> n >> k;
vector<int> cnt(n + 1, 0);
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
++cnt[x];
}
int mex = 0;
while (mex <= n && cnt[mex] > 0) ++mex;
ll uniqueCnt = 0, uniqueSum = 0;
int firstDup = -1;
for (int x = 0; x < mex; ++x) {
if (cnt[x] == 1) {
++uniqueCnt;
uniqueSum += x;
} else if (firstDup == -1) {
firstDup = x;
}
}
ll afterOne = uniqueSum + 1LL * mex * (n - uniqueCnt);
if (k == 1) {
cout << afterOne << '\n';
continue;
}
if (firstDup == -1) {
int p = mex;
if (p >= n - 1) {
cout << 1LL * n * (n - 1) / 2 << '\n';
continue;
}
ll base = 1LL * p * (p - 1) / 2;
ll low = base + 1LL * p * (n - p);
ll high = base + 1LL * (p + 1) * (n - p);
cout << (((k - 1) % 2 == 0) ? low : high) << '\n';
} else {
int p = firstDup;
ll base = 1LL * p * (p - 1) / 2;
ll low = base + 1LL * p * (n - p);
ll high = base + 1LL * (p + 1) * (n - p);
cout << (((k - 2) % 2 == 0) ? low : high) << '\n';
}
}
return 0;
}