Official

D - Flipping and Bonus Editorial by en_translator


The key fact is that, for \(0\leq i\leq N-1\), “if we know the value of the counter \(C\) when the \(I\)-th toss finished, the maximum amount of money we can earn in the \((i+1)\)-th through \(N\)-th toss is independent of the outcome of the \(1\)-st through \(i\)-th toss (as long as the value of the counter results in \(C\)).

Thus, it is sufficient to incrementally update the maximum amount of money obtained by the \(1\)-st through \(i\)-th toss subject to “after the first \(i\) tosses,” “the value of the counter becomes \(j\).” Let us denote this maximum value by \(dp[i][j]\) (where DP stands for Dynamic Programming). If such situation is impossible, that is, if \(i<j\), then let \(dp[i][j]=-\infty\).

First, we consider the initial value \(dp[0][j]\). Since the initial value of the counter is \(0\), we have \(dp[0][0]=0, dp[0][j]=-\infty\) \((j>0)\).

Next, we consider how to update the DP array. Let us consider how to compute \(dp[i_0+1][j]\) when we have obtained \(dp[i][j]\) for \(0\leq i\leq i_0\).
First, consider \(j_0>0\). Such case happens only if the counter shows \(j_0-1\) after the \(i_0\)-th toss and the coin heads in the \((i_0+1)\)-th toss. Thus, \(dp[i_0+1][j_0]=dp[i_0][j_0-1]+X_{i_0+1}+B_{j_0}\). Here, \(B_{j_0}\) is a streak bonus: \(B_{j_0}=Y_k\) if there exists \(k\) such that \(C_k=j_0\), or \(B_{j_0}=0\) otherwise.
Then, \(j_0=0\) holds only when the coin tails in the \((i_0+1)\)-th toss. Thus, \(dp[i_0+1][0]=\displaystyle\max_j(dp[i_0][j])\). Noting that \(dp[i_0][j]=-\infty\) if \(i_0<j\), we have \(dp[i_0+1][0]=\displaystyle\max_{0\leq j\leq i_0}(dp[i_0][j])\).

The answer is \(\displaystyle\max_{0\leq j\leq N}(dp[N][j])\).

The overall complexity is \(O(N^2)\), which is fast enough. Therefore, the problem has been solved.

Sample code in C++:

#include <bits/stdc++.h>
using namespace std;

int main(void) {
	int n, m;
	long long x[5001];
	long long c, y;
	long long b[5001], dp[5001][5001];
	long long ans;
	for (int i = 0; i <= n; i++)b[i] = 0;

	cin >> n >> m;
	for (int i = 0; i < n; i++)cin >> x[i + 1];
	for (int i = 0; i < m; i++) {
		cin >> c >> y;
		b[c] = y;
	}

	dp[0][0] = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= i; j++) dp[i][j] = dp[i - 1][j - 1] + x[i] + b[j];

		dp[i][0] = 0;
		for (int j = 0; j < i; j++)dp[i][0] = max(dp[i][0], dp[i - 1][j]);
	}

	ans = 0;
	for (int i = 0; i <= n; i++)ans = max(ans, dp[n][i]);
	cout << ans << endl;

	return 0;
}

posted:
last update: