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++ (Clang 10.0.0) (judge verdict: Wrong Answer)

#include <algorithm>
#include <array>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <optional>
#include <queue>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

int64_t read_int() {
    int64_t ret = 0, sgn = 1;
    int ch = getchar_unlocked();
    while (isspace(ch)) { ch = getchar_unlocked(); }
    if (ch == '-') { sgn = -1; ch = getchar_unlocked(); }
    for (; isdigit(ch); ch = getchar_unlocked())
        ret = (ret * 10) + (ch - '0');
    ungetc(ch, stdin);
    return sgn * ret;
}

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define FOR(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define ALL(c) (c).begin(), (c).end()

template <typename T> inline void assign_min(T& x, const T& value) noexcept { x = min(x, value); }
template <typename T> inline void assign_max(T& x, const T& value) noexcept { x = max(x, value); }

constexpr char LF = '\n';

//-------------------------------------------------------------------------------------------------

string read_word() {
    string ret;
    int ch = getchar_unlocked();
    while (isspace(ch)) { ch = getchar_unlocked(); }
    for (; ch != EOF && !isspace(ch); ch = getchar_unlocked())
        ret += ch;
    ungetc(ch, stdin);
    return ret;
}

// n以上の最小の2の冪を返す。
constexpr int bit_ceil(int n) noexcept {
    int ret = 1;
    while (ret < n) { ret *= 2; }
    return ret;
}

template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "[";
    bool first = true;
    for (const auto& x : v) {
        if (first) {
            first = false;
        } else {
            os << ", ";
        }
        os << x;
    }
    os << "]";
    return os;
}

template <typename K, typename V>
ostream& operator<<(ostream& os, const map<K, V>& m) {
    os << "{";
    bool first = true;
    for (const auto& [k, v] : m) {
        if (first) {
            first = false;
        } else {
            os << ", ";
        }
        os << k << ": " << v;
    }
    os << "}";
    return os;
}

template <typename T>
ostream& operator<<(ostream& os, const set<T>& s) {
    os << "{";
    bool first = true;
    for (const auto& x : s) {
        if (first) {
            first = false;
        } else {
            os << ", ";
        }
        os << x;
    }
    os << "}";
    return os;
}

template <typename T>
ostream& operator<<(ostream& os, const optional<T>& v) {
    if (v)
        os << *v;
    else
        os << "nullopt";
    return os;
}

struct SegmentTree {
    int n;
    vector<int> data;
    vector<int> argdata;

    explicit SegmentTree(int size):
        n(bit_ceil(size)), data(2*n-1, numeric_limits<int>::min()), argdata(2*n-1, -1) {}

    void set(int i, int value) {
        set_(i, value, 0, 0, n);
    }

    pair<int, int> max(int L, int R) {
        return max_(L, R, 0, 0, n);
    }

private:
    void set_(int i, int value, int u, int l, int r) {
        if (l == i && r == l+1) {
            data[u] = value;
            argdata[u] = i;
        } else {
            int m = (l + r) / 2;
            if (i < m) {
                set_(i, value, 2*u+1, l, m);
            } else {
                set_(i, value, 2*u+2, m, r);
            }
            if (data[2*u+1] < data[2*u+2]) {
                data[u] = data[2*u+2];
                argdata[u] = argdata[2*u+2];
            } else {
                data[u] = data[2*u+1];
                argdata[u] = argdata[2*u+1];
            }
        }
    }

    pair<int, int> max_(int L, int R, int u, int l, int r) {
        if (r < L || R <= l) { // この区間とクエリ区間が全く重ならないとき
            return {numeric_limits<int>::min(), -1};
        }
        if (L <= l && r <= R) { // この区間がクエリ区間に完全に包含されているとき
            return {data[u], argdata[u]};
        }
        // この区間とクエリ区間が部分的に重なるとき
        int m = (l + r) / 2;
        auto [max1, argmax1] = max_(L, R, 2*u+1, l, m);
        auto [max2, argmax2] = max_(L, R, 2*u+2, m, r);
        if (max1 < max2) {
            return {max2, argmax2};
        } else {
            return {max1, argmax1};
        }
    }
};

int main() {
    auto N = read_int();
    vector<string> S(N);
    REP(i, N) S[i] = read_word();

    int total_open = 0, total_close = 0, max_n_close = 0;
    vector<pair<int, int>> items(N);
    REP(i, N) {
        // 対応する括弧を削除して残る括弧の数を数える
        int n_open = 0, n_close_unmatched = 0;
        for (char ch : S[i]) {
            if (ch == '(') {
                n_open++;
                total_open++;
            } else {
                if (n_open > 0) { n_open--; }
                else { n_close_unmatched++; }
                total_close++;
            }
        }
        int n_open_unmatched = n_open;
        items[i] = {n_open_unmatched, n_close_unmatched};
        assign_max(max_n_close, n_close_unmatched);
    }

    if (total_open != total_close) {
        cout << "No" << LF;
        return 0;
    }

    // 閉じ括弧の数が k 以下であるものの中で (開き括弧) - (閉じ括弧) が一番大きいものを選びたい
    SegmentTree st(max_n_close+1);
    map<int, vector<int>> M;

    for (auto [n_open, n_close] : items) {
        M[n_close].emplace_back(n_open - n_close);
    }
    for (auto& [n_close, excesses] : M) {
        sort(ALL(excesses));
        st.set(n_close, excesses.back());
    }

    int current_open = 0;
    REP(i, N) {
        auto [ex, j] = st.max(0, current_open + 1);
        if (ex <= -10000000) {
            cout << "No" << LF;
            return 0;
        }
        auto& excesses = M[j];
        excesses.pop_back();
        if (excesses.empty()) {
            st.set(j, -10000000);
        } else {
            st.set(j, excesses.back());
        }
        current_open += ex;
    }
    cout << "Yes" << LF;
    return 0;
}