I - Happy Birthday! 3 Editorial by en_translator
Considering the operations in reverse order, the problem can be rephrased as follows:
Each piece \(i\) is initially painted in color \(C_i\). Find the minimum total cost required to make all pieces to have color \(0\) by repeating the following operation.
Choose \(a,b,c\) such that each of the pieces \(a, a + 1, \ldots, a + b - 1\) have color \(0\) or \(c\). Paint the pieces \(a, a + 1, \ldots, a + b - 1\) in color \(0\) for a cost \(b + X_c\).
From now on, we consider this rephrased problem.
We may assume that piece \(a\) and piece \(a + b - 1\) is always painted in color \(c\) (otherwise, the required cost is reduced by shrinking the segment).
Consider the last operation performed. Assume that the last operation was performed against pieces \(a, a + 1, \ldots, a + b - 1\). Since pieces \(a\) and \(a + b - 1\) was painted in color \(c\) before the last operation, we see that no single operation has been performed against a piece contained in \(\lbrace a, a + 1, \ldots, a + b - 1 \rbrace\) and another not contained simultaneously. Therefore, the minimum cost required when the last operation was performed against pieces \(a, a + 1, \ldots, a + b - 1\) can be found as the sum of the minimum costs required to make pieces \(a, a + 1, \ldots, a + b - 1\) to have color \(0\) and make the other pieces to have color \(0\) independently.
Thus, the problem can be divided into a problem of a smaller size. This allows us to consider a DP (Dynamic Programming). The original problem against a circle has been divided into problems against sequences, but by the observation above it turns out that we can consider all possible positions to cut a circle to form a sequence, solve the problem against each of them, and report the minimum value among them as the answer.
Let \(dp_{l, r}\) be the minimum cost required to make pieces \(l, l + 1, \ldots, r - 1\) color \(0\). We compute \(dp_{l, r}\) by case discussion whether the last operation was performed against pieces \(l, l + 1, \ldots, r - 1\).
First, suppose that the last operation was performed against pieces \(l, l + 1, \ldots, r - 1\). Let’s say the last operation was performed against pieces \(l' , l' + 1, \ldots, r' - 1\). Then \(l \neq l'\) or \(r \neq r'\), but if \(l \neq l'\), then \(l, l + 1, \ldots, l' - 1\) and \(l', l' + 1, \ldots, r - 1\) can be considered independently; if \(r \neq r'\), then \(l, l + 1, \ldots, r' - 1\) and \(r', r' + 1, \ldots, r - 1\) can be considered independently. Therefore, the minimum cost for this case is the minimum value of \(dp_{l, m} + dp_{m, r}\) for \(m\) with \(l < m < r\).
Next, suppose that the last operation was performed against pieces \(l, l + 1, \ldots, r - 1\). The sought cost is the minimum cost required to make each of pieces \(l, l + 1, \ldots, r - 1\) color \(0\) or color \(C_l\), plus \(r - l + X_{C_l}\). (Note that piece \(l\) remains color \(C_l\).) The minimum cost required to make each of pieces \(l, l + 1, \ldots, r - 1\) color \(0\) or color \(C_l\) can be found with another DP. Specifically, its DP array \(ep\) can be calculated by transitions \(ep_{l, r} \leftarrow \min(ep_{l, r}, \min(ep_{l, m} + dp_{m, r}))\) (which corresponds to making piece \(r - 1\) color \(0\); we consider the leftmost piece against pieces \(l, l + 1, \ldots, r - 2\) that is kept to be color \(C_l\)) and transitions \(ep_{l, r} \leftarrow \min(ep_{l, r}, ep_{l, r - 1})\) if \(C_{r - 1} = C_l\) (which corresponds to keeping piece \(r - 1\) to be color \(C_l\)).
After filling the DP table, the final answer can be found as \(\min_{0 \leq i < N} dp_{i, N + i}\).
The total time complexity is \(O(N^3)\).
Sample code
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
using namespace std;
using ll = long long;
const ll INF = 1000000000000000010;
template<class T, class U> inline bool chmin(T& a, const U& b) { if (a > b) { a = b; return true; } return false; }
int main() {
int n;
cin >> n;
vector<int> c(2 * n);
rep(i, n) {
cin >> c[i];
c[i]--;
c[n + i] = c[i];
}
vector<int> x(n);
rep(i, n) cin >> x[i];
vector dp(2 * n + 1, vector(2 * n + 1, INF)); // Cost to fill with color 0
vector ep(2 * n + 1, vector(2 * n + 1, INF)); // Cost to fill with color 0 or c[l]
rep(i, 2 * n + 1) { dp[i][i] = 0, ep[i][i] = 0; }
for (int l = 2 * n; l >= 0; l--) {
for (int r = l + 1; r <= 2 * n; r++) {
for (int m = l + 1; m < r; m++) {
chmin(dp[l][r], dp[l][m] + dp[m][r]);
chmin(ep[l][r], ep[l][m] + dp[m][r]);
}
if (c[l] == c[r - 1]) {
chmin(ep[l][r], ep[l][r - 1]);
chmin(dp[l][r], ep[l][r] + r - l + x[c[l]]);
}
}
}
ll ans = INF;
rep(i, n) chmin(ans, dp[i][n + i]);
cout << ans << '\n';
}
posted:
last update: