B - プレイリストの最適化 / Playlist Optimization 解説 by admin
claude4.8opus-highOverview
This problem asks us to find the minimum “total discomfort” when playing \(N\) songs in some order. To state the conclusion first: the answer can be found simply by sorting the tempo values and summing up the differences between adjacent values wherever that difference is strictly greater than \(D\).
Analysis
Grouping by Similarity
First, let us sort the tempo values in ascending order. Within this sorted sequence, songs whose “adjacent difference is \(D\) or less” are similar to each other. Therefore, by splitting the sequence at any point where the difference is strictly greater than \(D\), we can partition the songs into multiple groups (clusters).
As an example, consider \(A = [1, 3, 10, 12, 100]\) and \(D = 2\). The array is already sorted, and the differences between adjacent elements are \(2, 7, 2, 88\) respectively. The differences strictly greater than \(D=2\) are \(7\) and \(88\), so the songs are partitioned into the following \(3\) groups:
\[\{1, 3\} \mid \{10, 12\} \mid \{100\}\]
Here, we have an important property: - Songs in the same group are connected by a chain of adjacent differences of \(D\) or less. Thus, if we play them in a suitable order, we can always guarantee that “a similar song has already been played.” - Songs in different groups have a gap of strictly greater than \(D\) between them, so they can never be considered “similar” to each other.
What Happens if We Play in Sorted Order?
Let’s see what happens if we play the songs in sorted order (from smallest to largest).
- Within a group, the difference between a song and its immediate predecessor is at most \(D\). Thus, a similar song has already been played, resulting in a discomfort score of \(0\).
- At the boundary of a group (where the difference is strictly greater than \(D\)), the song’s difference from all previously played songs is strictly greater than \(D\) (since all previous songs are smaller than it, and the closest one is its immediate predecessor). Therefore, no similar song exists in the history, and the discomfort score is \(|B_j - B_{j-1}|\), which is exactly this difference itself.
In our previous example, playing in the sorted order \(1, 3, 10, 12, 100\) yields: - \(1\): First song, so score is \(0\). - \(3\): Since \(|3-1|=2 \le 2\), a similar song exists \(\to\) score is \(0\). - \(10\): The difference with the predecessor \(3\) is \(7 > 2\). No similar song exists \(\to\) score is \(7\). - \(12\): Since \(|12-10|=2 \le 2\) \(\to\) score is \(0\). - \(100\): The difference with the predecessor \(12\) is \(88 > 2\) \(\to\) score is \(88\).
The total score is \(7 + 88 = 95\). This exactly matches the “sum of differences at the boundaries where the difference is strictly greater than \(D\).”
Why This is Optimal
If there are \(m\) groups, the “first played song” of each group (except for the first song played overall) must incur a discomfort score because no other member of its group has been played yet. In other words, we must pay a cost to “connect” these \(m\) groups.
The minimum cost to connect \(m\) groups on a number line is the sum of all gaps (differences strictly greater than \(D\)) between adjacent groups (this is the same concept as the Minimum Spanning Tree on a 1D line: jumping across groups over larger distances is suboptimal, so entering a group from its immediate neighbor is optimal). Playing the songs in sorted order achieves exactly this minimum cost.
Why a Naive Approach Fails
Trying all possible playing orders would take \(O(N!)\) time, which is far too slow for \(N \le 10^6\). Instead of searching for the order directly, recognizing the structure described above allows us to find the answer with a single sort.
Algorithm
- Sort the tempo array \(A\) in ascending order.
- Check the adjacent differences \(A_i - A_{i-1}\) in order, and add the difference to the answer only when it is strictly greater than \(D\).
- The accumulated sum is the final answer.
Sort A
ans = Σ (A[i] - A[i-1]) only for terms where (A[i] - A[i-1]) > D
Complexity
- Time Complexity: \(O(N \log N)\) (dominated by sorting)
- Space Complexity: \(O(N)\) (to store the tempo values)
Implementation Details
Beware of Integer Overflow: Since the differences can be up to \(10^9\) and there are up to \(10^6\) terms, the total sum can be as large as \(10^{15}\). Since this will overflow a standard 32-bit
int, make sure to use 64-bit integers (long longin C++) for the answer and difference calculations.Boundary of “at most \(D\)” vs “strictly greater than \(D\)”: Songs are similar if the difference is at most \(D\) (\(\le D\)), so we only add to the sum when the difference exceeds \(D\) (
diff > D). Be careful with the inequality.Fast I/O: Since \(N \le 10^6\), the input size is quite large, so the speed of
scanforcinbecomes important. In the sample code, a custom fast I/O usingfreadis used (if you usecin, it is recommended to includeios::sync_with_stdio(false)for speedup).Source Code
#include <bits/stdc++.h>
using namespace std;
static char buf[1 << 25];
int bufLen = 0, bufPos = 0;
inline int readByte() {
if (bufPos == bufLen) {
bufLen = (int)fread(buf, 1, sizeof(buf), stdin);
bufPos = 0;
if (bufLen == 0) return -1;
}
return buf[bufPos++];
}
inline long long readLL() {
int c = readByte();
while (c != '-' && (c < '0' || c > '9')) {
if (c == -1) return -1;
c = readByte();
}
bool neg = false;
if (c == '-') { neg = true; c = readByte(); }
long long x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + (c - '0');
c = readByte();
}
return neg ? -x : x;
}
int main() {
long long N = readLL();
long long D = readLL();
vector<int> a((size_t)N);
for (long long i = 0; i < N; i++) {
a[(size_t)i] = (int)readLL();
}
sort(a.begin(), a.end());
long long ans = 0;
for (long long i = 1; i < N; i++) {
long long diff = (long long)a[(size_t)i] - (long long)a[(size_t)(i - 1)];
if (diff > D) ans += diff;
}
printf("%lld\n", ans);
return 0;
}
This editorial was generated by claude4.8opus-high.
投稿日時:
最終更新: