Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Editorial

Define dp[i] to be the maximum Cypriot value of the subarray a[i...]. Then, we can apply some choices for the first element.

  • We can either allot a single cut to just this element.
  • It can be merged with its neighbor.

If it is merged with its neighbor, then, of course, we want to maximise the Cypriot value of a[i + 1 ...] before doing the merge. This is nothing but dp[i].

However, when we cut the first element alone, we can’t just blindly reuse the DP value of a[i + 1 ...] because that DP maximizes

E1 = 1*s1 + 2*s2 + 3*s3 + ... 

while we want to maximize

E2 = 2*s2 + 3*s3 + 4*s3

But notice that

E2 - E1 = suffix_sum
E2 = E1 + suffix_sum

Hence, to maximize E2, since the suffix sum is fixed, we can, in fact, use the maximized E1.

Hence, the DP transitions look like:

long long solve(vector<long long> &a) {
    int n = a.size();

    vector<long long> suffix_sum = a;
    for (int i = n - 2; i >= 0; i--) {
        suffix_sum[i] += suffix_sum[i + 1];
    }

    vector<long long> dp(n, 0);
    // dp[i] is the answer for a[i ... ]

    dp[n - 1] = a[n - 1];
    for (int i = n - 2; i >= 0; i--) {
        // Cut alone.
        auto cut_alone = a[i] + dp[i + 1] + suffix_sum[i + 1];

        // Cut with the group.
        auto cut_with_group = a[i] + dp[i + 1];

        dp[i] = max(cut_alone, cut_with_group);
    }

    return dp[0];
}

DP vs Greedy

Notice that pseudocode above. At first glance, you can definitely say that it’s DP since we simulated both the choices and took the best one out of them. Now, let’s do a series of refactoring and code cleanup.

Since dp[i] = max(cut_alone, cut_with_group), we can replace it with dp[i] = cut_alone if cut_alone is bigger than cut_with_group and vice-versa. When could cut_alone be greater than cut_with_group?

cut_alone > cut_with_group
a[i] + dp[i + 1] + suffix_sum[i + 1] > a[i] dp[i + 1]
suffix_sum[i + 1] > 0

Hence

dp[i] = a[i] + dp[i + 1]
dp[i] += suffix_sum[i + 1] if it is > 0

Now, try to read the statement above in english. You can say that you start with the last element with a running sum, and if the suffix sum is greater than 0, add it to the running sum. Also, notice that cut_alone would be greater than cut_with_group if suffix_sum is positive (as derived earlier). Hence, we even have an intuition that we should greedily cut the i-th element alone if the suffix sum is positive.

So now, would you call this approach greedy or DP. Why or why not? Let me know on the comment thread