Official

B - Parenthesis Arrangement Editorial by evima


[1] Correct Parenthesis Sequence Reformulation

The condition of being a correct parenthesis sequence can be reformulated as follows: the string has an equal number of (s and )s, and the minimum cumulative sum of the sequence obtained by replacing ( with \(+1\) and ) with \(-1\) is \(0\).

The reformulated conditions are easier to handle, so we use this version below.


[2] Solution

In the first operation, the number of (s does not change, so it is necessary to equalize the number of (s and )s by the second operation.

Let \(p\) be the number of (s and \(q\) be the number of )s, then the required number of second operations can be determined as \(\frac{|p-m|}{2}\).

From the reformulated conditions, it can be seen that if we are to replace ( with ), it is optimal to do it from right to left, and it is optimal to replace ) with ( from left to right.

Next, we consider the number of operations required to satisfy the condition that “the minimum cumulative sum of the sequence obtained by replacing ( with \(+1\) and ) with \(-1\) is \(0\)” by the first operation.

Similar to the discussion regarding the second operation, it suffices to consider only the operation of swapping the leftmost ) with the rightmost (. One operation increases the minimum cumulative sum by \(2\), so let \(l\) be the current minimum cumulative sum, then the required number of operations can be determined as \(\lceil\frac{-l}{2}\rceil\).

Note that two second operations can be substituted for the first operation, so we need to replace \(A\) with \(\min{(A,2B)}\) beforehand.

All the above processes can be performed in \(\mathrm{O}(N)\).


[3] Sample Implementation (C++)

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

int main() {
    int n;
    long long a, b;
    cin >> n >> a >> b;
    a = min(a, 2 * b);
    string s;
    cin >> s;
    int p = count(s.begin(), s.end(), '(');
    int m = 2 * n - p;
    int d = p - m;
    long long res = 0;
    if(p > m) {
        for(int i = 2 * n - 1; i >= 0; --i) {
            if(s[i] == '(' and d) {
                d -= 2;
                s[i] = ')';
                res += b;
            }
        }
    } else {
        for(int i = 0; i < 2 * n; i++) {
            if(s[i] == ')' and d) {
                d += 2;
                s[i] = '(';
                res += b;
            }
        }
    }
    long long cum = 0, mn = 0;
    for(int i = 0; i < 2 * n; i++) {
        cum += (s[i] == '(' ? 1 : -1);
        mn = min(mn, cum);
    }
    res += (-mn + 1) / 2 * a;
    cout << res << endl;
}

posted:
last update: