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: Accepted)

#include<bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
const int MAXN = 1e6 + 7;
const int INF = 1e9;
vector<pii>vec;
char s[MAXN];
stack<char>stk;
int N, a[MAXN], v[MAXN];
    
#define lson (rt << 1)
#define rson (rt << 1 | 1)
struct node{int val, pos;} T[MAXN << 2];
node merge(node &x, node &y) {
    if (x.val > y.val) return x;
    else return y;
}
void pushup(int rt) {T[rt] = merge(T[lson], T[rson]);}
void build(int rt, int l, int r) {
    if (l == r) {T[rt] = {v[l], l}; return;}
    int mid = (l + r) >> 1;
    build(lson, l, mid);
    build(rson, mid + 1, r);
    pushup(rt);
}
void update(int rt, int l, int r, int pos, int v) {
    if (l == r) {T[rt] = {v, l}; return;}
    int mid = (l + r) >> 1;
    if (pos <= mid) update(lson, l, mid, pos, v);
    else update(rson, mid + 1, r, pos, v);
    pushup(rt);
}
node query(int rt, int l, int r, int L, int R) {
    if (L <= l && r <= R) return T[rt];
    int mid = (l + r) >> 1;
    node resl = {-INF, -1}, resr = {-INF, -1};
    if (L <= mid) resl = query(lson, l, mid, L, R);
    if (mid <  R) resr = query(rson, mid + 1, r, L, R);
    return merge(resl, resr);
}
    
int main() {
    int n; scanf("%d", &n);
    int sum1 = 0, sum2 = 0;
    for (int k = 1; k <= n; k++) {
        scanf(" %s", s);
        int len = strlen(s);
        for (int i = 0; i < len; i++) {
            if (s[i] == '(') stk.push(s[i]);
            else {
                if (stk.size() && stk.top() == '(') stk.pop();
                else stk.push(s[i]);
            }
        }
        pii item = {0, 0};
        while (stk.size()) {
            if (stk.top() == '(') item.second++;
            else item.first++;
            stk.pop(); 
        }
        if (item.first == 0) sum1 += item.second;
        else if (item.second == 0) sum2 += item.first;
        else vec.push_back(item);
    }
    sort(vec.begin(), vec.end());
    N = vec.size();
    for (int i = 1; i <= N; i++) {
        a[i] = vec[i - 1].first;
        v[i] = vec[i - 1].second - vec[i - 1].first;
    }
    if (N > 0) build(1, 1, N);
    for (int i = 1; i <= N; i++) {
        int p = upper_bound(a + 1, a + 1 + N, sum1) - a - 1;
        if (!p) {puts("No"); return 0;}
        node res = query(1, 1, N, 1, p);
        if (res.pos == -1 || sum1 < a[res.pos]) {puts("No"); return 0;}
        sum1 += v[res.pos];
        update(1, 1, N, res.pos, -INF);
    }
    sum1 == sum2 ? puts("Yes") : puts("No");
    return 0;
}