Problem:
Score : 600 points

Problem Statement

A bracket sequence is a string that is one of the following:

An empty string;

The concatenation of (, A, and ) in this order, for some bracket sequence A ;

The concatenation of A and B in this order, for some non-empty bracket sequences A and B /

Given are N strings S_i. Can a bracket sequence be formed by concatenating all the N strings in some order?

Constraints

1 \leq N \leq 10^6

The total length of the strings S_i is at most 10^6.

S_i is a non-empty string consisting of ( and ).

Input

Input is given from Standard Input in the following format:

N
S_1
:
S_N

Output

If a bracket sequence can be formed by concatenating all the N strings in some order, print Yes; otherwise, print No.

Sample Input 1

2
)
(()

Sample Output 1

Yes

Concatenating (() and ) in this order forms a bracket sequence.

Sample Input 2

2
)(
()

Sample Output 2

No

Sample Input 3

4
((()))
((((((
))))))
()()()

Sample Output 3

Yes

Sample Input 4

3
(((
)
)

Sample Output 4

No

Solution in C++ (GCC 9.2.1) (judge verdict: Runtime Error)

#include <iostream>
#include <sstream>
#include <stack>
#include <iomanip>
#include <numeric>
#include <string>
#include <cstring>
#include <algorithm>
#include <functional>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <queue>
#include <cmath>

#define BEGIN(x) x.begin()
#define END(x) x.end()
#define ALL(x) BEGIN(x), END(x)
#define PAIR make_pair
#define VEC(type) vector<type >
#define endl '\n'

#define FOR(i, A, B) for(auto i = (A);i != (B); i++)
#define FORD(i, A, B) for(auto i = (A);i != (B); i--)

#define READRANGE(begin, end) FOR(it, begin, end) cin >> *it
#define READVEC(V) READRANGE(BEGIN(V), END(V))

using namespace std;

typedef long long lint;
typedef pair<int, int> Pii;
typedef pair<int, lint> Pil;
typedef pair<lint, lint> Pll;
typedef pair<lint, int> Pli;

template<class U, class V>
istream& operator >>(istream& in, pair<U, V>& pr) {
    return in >> pr.first >> pr.second;
}

// ---- BEGIN LIBRARY CODE ----
/**
 * 1-D Segment Tree data structure. Supports element updates and binary
 * associative operations over range like (addition, max, min) in logarithmic
 * time. Space usage is linear in n. Works with numeric data types like
 * 32/64 bit integers and doubles.
 */
template<class T>
class SegmentTree
{
public:
    SegmentTree(int _n, T _initial, const function<T(T, T)> _op)
    {
        n = _n;
        op = _op;
        initial = _initial;
        tree.clear();
        tree.resize(4 * n + 5, initial);
    }

    /** Updates a single element at index x to newval. */
    void update(int x, T newval)
    {
        stack<int> pathToX;
        int i = 0, l = 0, r = n - 1;
        while (l < x || r > x) {
            pathToX.push(i);
            int m = (l + r) / 2;
            if (x > m) {
                l = m + 1;
                i = 2 * i + 2;
            } else {
                r = m;
                i = 2 * i + 1;
            }
        }

        tree[i] = newval;

        // move back upto the root, updating all the nodes in the path.
        while (!pathToX.empty()) {
            int i = pathToX.top();
            pathToX.pop();
            tree[i] = op(tree[2 * i + 1], tree[2 * i + 2]);
        }
    }

    T rangeQuery(int x, int y)
    {
        return rangeQuery(x, y, 0, 0, n - 1);
    }
private:
    /** Returns the result of the operator performed over the entire 
      range specified by [x, y], both ends inclusive. */
    T rangeQuery(int x, int y, int i, int l, int r)
    {
        if (x > y)
            return initial;

        if (x <= l && y >= r)
            return tree[i];

        int m = (l + r) / 2;
        if (y <= m)
            return rangeQuery(x, y, 2 * i + 1, l, m);
        else if (x > m)
            return rangeQuery(x, y, 2 * i + 2, m + 1, r);

        T half1 = rangeQuery(x, m, 2 * i + 1, l, m);
        T half2 = rangeQuery(m + 1, y, 2 * i + 2, m + 1, r);
        return op(half1, half2);
    }

    int n;
    T initial;
    function<T(T, T)> op;
    vector<T> tree;
};
// ---- END LIBRARY CODE ----
void io_init()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
};

const int _INF = 1 << 20;

Pii processString(string& s)
{
    int depth = 0, minb = 0;
    for (char c : s) {
        if (c == ')')
            depth--;
        else
            depth++;
        minb = max(minb, -depth);
    }

    return Pii(minb, depth);
};

int main(int argc, char **argv)
{
    io_init();

    // Actual program code starts here.
    function<Pii(Pii, Pii)> oper = [](Pii a, Pii b) {
        if (a.second < b.second) {
            return b;
        } else if (a.second > b.second)
            return a;

        if (a.first > b.first)
            return a;
        return b;
    };

    SegmentTree<Pii> segTree(1000001, Pii(-1, -_INF), oper);
    int N;
    cin >> N;

    VEC(VEC(int)) strsByM(1000001);
    FOR(i, 0, N) {
        string s;
        cin >> s;
        Pii pr = processString(s);
        int minb = pr.first, dep = pr.second;
        strsByM[minb].push_back(dep);
    }

    FOR(i, 0, strsByM.size()) {
        if (!strsByM[i].empty()) {
            sort(ALL(strsByM[i]));
            segTree.update(i, Pii(i, strsByM[i].back()));
        } else segTree.update(i, Pii(i, _INF));
    }

    int curb = 0;
    FOR(i, 0, N) {
        Pii best = segTree.rangeQuery(0, curb);
        if (curb + best.second < 0) {
            cout << "No" << endl;
            return 0;
        }

        curb += best.second;

        int pos = best.first;
        strsByM[pos].pop_back();
        int newval = strsByM[pos].empty() ? -_INF : strsByM[pos].back();
        segTree.update(pos, Pii(pos, newval));
    }
     
    if (curb == 0)
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
    return 0;
};