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 song durations. Every action advances exactly one position in the infinite playlist, either by skipping or by listening fully. So minimizing skips is the same as minimizing the total number of played/visited playlist entries.
Convert every desired song into its position in the current playlist : let . Now the whole problem is about walking through the cyclic array positions .
From position to , you only wrap around the end of when . Each such wrap costs one extra full cycle of length .
If is the number of descents , then the total number of playlist entries encountered is , so the answer is .
For updates, maintain only the descent indicators between adjacent entries of . A swap in changes indicators near the swapped indices; a swap in changes positions of two songs, so it changes indicators near where those two songs occur in . That's constant work, not a segment tree circus.
Research checked: the official Codeforces statement at https://codeforces.com/problemset/problem/2206/J and the official tutorial PDF at https://codeforces.com/contest/2206/attachments/download/36244/analysis.pdf. The tutorial's core observation is the wrap-count formula; the explanation below expands the proof and update mechanics.
Let
where is the current position of song inside playlist permutation .
After this conversion, the actual song labels stop mattering. We only need to listen to positions
in this order while walking forward around a cyclic array of length .
Suppose we just listened to , currently at position in .
Since is a permutation, equal positions never happen for adjacent songs. No sneaky tie case, thank god.
Define
This is exactly the number of wraps before finishing all desired songs.
Now compute the total number of playlist entries encountered. If there were no cyclic wrapping, ending at position would mean exactly entries from the start. Each wrap adds one full extra cycle of entries. Therefore:
Exactly of those entries are listened to in full, one for each desired song. Everything else is skipped, so
That is the whole math. The rest is just not botching the updates.
Maintain:
a[pos]: song at position pos in playlist ,whereA[song]: current ,b[i]: desired song at index i,whereB[song]: current position of song inside ,bad[i] for :
Then
So the current answer is
If we swap and , only adjacent comparisons touching indices or can change:
We remove their old contributions, swap the two values, update whereB, then add their new contributions.
If we swap and , the only songs whose values change are those two songs:
A changed song position can only affect descent comparisons where that song appears in , so again only constant many indices matter:
Remove those contributions, swap the songs in a, update whereA, then add contributions back.
Use a tiny list of candidate indices and deduplicate it, because when and are close, the same bad[i] can appear twice. Double-removing a contribution is the kind of bug that makes you question free will.
We prove that the algorithm outputs the minimum number of skips for every day.
First, for fixed permutations and , consider . Starting from , to hear first, every playlist entry before position must be skipped, and listening to consumes position . There is no alternative route because the playlist order is fixed and only moves forward.
For every transition from to , the next listened song must be the first future occurrence of in the infinite playlist. If , that occurrence is in the same cycle; otherwise it is in the next cycle. Thus a wrap happens exactly when .
After all transitions, the final listened song is at position in the current cycle, plus one full cycle for each wrap. Therefore the total number of playlist entries encountered is exactly
Among these entries, exactly are listened to fully. Every other encountered entry must have been skipped, and skipping fewer is impossible because those entries occur before the next required full song. Hence the minimum number of skips is
Now for updates. The value depends only on adjacent comparisons
Swapping two entries of changes only comparisons adjacent to the swapped indices, so recomputing those indicators preserves the exact sum . Swapping two entries of changes only the positions of the two swapped songs; a descent indicator can change only if one of those songs is one of its two endpoints in , so recomputing the indicators adjacent to their positions in also preserves the exact sum .
Thus after every update, the maintained is correct, and by the formula above the printed answer is correct.
Initialization is . Each update touches candidate descent positions, so each day is processed in time.
Total complexity:
with memory.
#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 n, d;
cin >> n >> d;
vector<int> a(n + 1), b(n + 1), posA(n + 1), posB(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
posA[a[i]] = i;
}
for (int i = 1; i <= n; i++) {
cin >> b[i];
posB[b[i]] = i;
}
auto bad = [&](int i) -> int {
if (i < 1 || i >= n) return 0;
return posA[b[i]] > posA[b[i + 1]];
};
ll wraps = 0;
for (int i = 1; i < n; i++) wraps += bad(i);
auto answer = [&]() -> ll {
return (ll)posA[b[n]] + wraps * n - n;
};
auto norm = [&](vector<int> v) {
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
vector<int> res;
for (int x : v) {
if (1 <= x && x < n) res.push_back(x);
}
return res;
};
cout << answer() << '\n';
for (int day = 1; day < d; day++) {
int c, x, y;
cin >> c >> x >> y;
vector<int> affected;
if (c == 1) {
int s1 = a[x], s2 = a[y];
affected = norm({posB[s1] - 1, posB[s1], posB[s2] - 1, posB[s2]});
for (int i : affected) wraps -= bad(i);
swap(a[x], a[y]);
posA[s1] = y;
posA[s2] = x;
for (int i : affected) wraps += bad(i);
} else {
affected = norm({x - 1, x, y - 1, y});
for (int i : affected) wraps -= bad(i);
int s1 = b[x], s2 = b[y];
swap(b[x], b[y]);
posB[s1] = y;
posB[s2] = x;
for (int i : affected) wraps += bad(i);
}
cout << answer() << '\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 n, d;
cin >> n >> d;
vector<int> a(n + 1), b(n + 1), posA(n + 1), posB(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
posA[a[i]] = i;
}
for (int i = 1; i <= n; i++) {
cin >> b[i];
posB[b[i]] = i;
}
auto bad = [&](int i) -> int {
if (i < 1 || i >= n) return 0;
return posA[b[i]] > posA[b[i + 1]];
};
ll wraps = 0;
for (int i = 1; i < n; i++) wraps += bad(i);
auto answer = [&]() -> ll {
return (ll)posA[b[n]] + wraps * n - n;
};
auto norm = [&](vector<int> v) {
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
vector<int> res;
for (int x : v) {
if (1 <= x && x < n) res.push_back(x);
}
return res;
};
cout << answer() << '\n';
for (int day = 1; day < d; day++) {
int c, x, y;
cin >> c >> x >> y;
vector<int> affected;
if (c == 1) {
int s1 = a[x], s2 = a[y];
affected = norm({posB[s1] - 1, posB[s1], posB[s2] - 1, posB[s2]});
for (int i : affected) wraps -= bad(i);
swap(a[x], a[y]);
posA[s1] = y;
posA[s2] = x;
for (int i : affected) wraps += bad(i);
} else {
affected = norm({x - 1, x, y - 1, y});
for (int i : affected) wraps -= bad(i);
int s1 = b[x], s2 = b[y];
swap(b[x], b[y]);
posB[s1] = y;
posB[s2] = x;
for (int i : affected) wraps += bad(i);
}
cout << answer() << '\n';
}
return 0;
}