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.
Rewrite the operation in terms of values, not indices. It always uses three consecutive values , with sitting to the left of the other two.
A position with current value can only be lowered by at a time, so parity is locked. If it ever becomes , then .
To lower value all the way to , every value from to must be to its right. Otherwise at some step the needed pair is blocked on the left.
So while trying to place the next smallest number , scan values . A value is usable exactly when its position is a new record minimum among positions of values , and has the same parity as .
Pick the leftmost usable position for . Then simulate the whole chain in one shot: set that position to , and increase every value in by . Repeat for .
The operation looks index-based, but the real structure is value-based.
If an operation is performed with some , the three involved values are exactly:
The value must be at the leftmost chosen index. After the operation, that leftmost index gets value .
So the operation is basically: if a value has the two consecutive smaller values somewhere to its right, it may drop by . The two smaller values get pushed upward by .
Do not just greedily apply the first currently valid operation. That can lose. Order matters, and blindly spamming moves is how you get a very confident wrong answer. The correct greedy is about deciding where each final value goes.
Key Question
Suppose we are currently trying to place the smallest not-yet-fixed value, call it .
Which current values can be turned into ?
There are two requirements.
First, parity:
can only decrease by each time, so we need and to have the same parity.
Second, all smaller needed values must be on the right.
To reduce to , we need values and to the right of .
Then to reduce to , we need and to the right.
Continuing this, to reduce all the way to , every value in must be to the right of the position containing .
Equivalently:
vcpos[v]pos[x]c <= x < vv \equiv c \pmod 2
That means must be a new leftmost record while scanning values from upward.
Greedy Choice
We build the answer by placing values .
When placing , all values smaller than are already fixed. Among all feasible values that can become , we choose the one with the leftmost position.
Why? Because the final permutation is compared left to right. If we can place at some index, placing it farther right is instantly worse: at the earlier feasible index, the other answer has something larger than . No later cleverness can fix that. Lexicographic order is brutal like that.
How do we find the leftmost feasible value?
Scan and keep:
.
Whenever becomes a new minimum, value satisfies the right-side condition. If its parity matches , it is feasible. Since record positions strictly move left, the last feasible record we see is the leftmost feasible position.
There is always at least one feasible choice: itself.
Simulating Many Operations At Once
Suppose we chose position cur, whose current value is , and we want to turn it into .
Actually doing all operations one by one is unnecessary.
The chain does this:
Example: reducing to uses pairs and . In the end:
, , , , and .
So it is just a rotation of values .
Implementation-wise:
val = p[cur].p[cur] = c.x in [c, val-1], increment the element at pos[x].pos[val] = old pos[val-1], ..., pos[c+1] = old pos[c], and pos[c] = cur.Then continue with .
Correctness Sketch
A value can become only if parity matches and every value is to its right. Necessity comes directly from the operation requirements at each decrease step.
Those conditions are also sufficient: reduce by repeatedly. At each step, the next two needed smaller values are still to the right, so the operation is valid.
The greedy choice is forced by lexicographic order. At step , all smaller values are already fixed. The first place where the final array can improve is the position where we put . Therefore putting at the leftmost feasible position is always optimal.
After applying the one-shot rotation, the remaining unfixed values are exactly , still forming a permutation, so the same argument applies recursively.
Thus the algorithm constructs the lexicographically smallest reachable permutation.
Complexity
For each , we scan up to values and do up to update work. So the complexity is per test case, which is exactly what the easy version allows.
#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> p(n), pos(n + 1);
for (int i = 0; i < n; i++) {
cin >> p[i];
pos[p[i]] = i;
}
for (int want = 1; want <= n; want++) {
int cur = n;
int mn = n;
for (int val = want; val <= n; val++) {
if (pos[val] < mn) {
mn = pos[val];
if ((val & 1) == (want & 1)) {
cur = pos[val];
}
}
}
int val = p[cur];
p[cur] = want;
for (int x = want; x < val; x++) {
p[pos[x]]++;
}
for (int x = val; x > want; x--) {
pos[x] = pos[x - 1];
}
pos[want] = cur;
}
for (int i = 0; i < n; i++) {
if (i) cout << ' ';
cout << p[i];
}
cout << '\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> p(n), pos(n + 1);
for (int i = 0; i < n; i++) {
cin >> p[i];
pos[p[i]] = i;
}
for (int want = 1; want <= n; want++) {
int cur = n;
int mn = n;
for (int val = want; val <= n; val++) {
if (pos[val] < mn) {
mn = pos[val];
if ((val & 1) == (want & 1)) {
cur = pos[val];
}
}
}
int val = p[cur];
p[cur] = want;
for (int x = want; x < val; x++) {
p[pos[x]]++;
}
for (int x = val; x > want; x--) {
pos[x] = pos[x - 1];
}
pos[want] = cur;
}
for (int i = 0; i < n; i++) {
if (i) cout << ' ';
cout << p[i];
}
cout << '\n';
}
}