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<iostream>
using namespace std;

int n;
string s[1000000];
int lr[1000000];
int l[1000000];
int r[1000000];
//int rdep[1000000];
int temp[1000000];
int tempb[1000000];
int tempc[1000000];
int flag[1000000];
/*long long int n, k;
long long int a[200001];
long long int flag[200001];*/

/*int n, m, x;
int c[12];
int a[12][12];
int un[12];
*/

void margesort(int a[], int a_len, int left, int right,int lr);

//int dfs(int u[], int k, int money);
int main() {

	//まず合計を判断
	//その後)の深さに耐えられるかの判断



	cin >> n;
	int i, j;
	//int l, r;
	int lrs = 0;
	for (i = 0; i < n; i++) {
		cin >> s[i];
		flag[i] = 0;
		l[i] = 0;
		r[i] = 0;
		lr[i] = 0;
		for (j = 0; j < s[i].length(); j++) {
			if (s[i][j] == ')'){
				if (l[i] == 0) {
					r[i]++;
				}
				else {
					l[i]--;
				}
			}
			else {
				l[i]++;
			}
		}
		//cout << l[i] << r[i] << endl;
		lr[i] = l[i] - r[i];
		lrs = lrs + lr[i];
	}
	if (lrs != 0) {
		cout << "No\n";
		return 0;
	}
	margesort(r,n,0,n-1,0);
	int lrsum = 0;
	int checker = n;
	for (i = 0; i < n; i++) {

		/*if (r[i] == 0) {
			lrsum = lrsum + l[i];
			//cout << l[i];
			flag[i] = 1;
			checker--;
		}*/
		if (l[i] - r[i] >= 0) {
			if (lrsum >= r[i]) {
				lrsum = lrsum + l[i] - r[i];
				flag[i] = 1;
				//cout << lrsum;

			}
			else {
				cout << "No\n";
				return 0;
			}
		}
	}
	margesort(l, n, 0, n - 1,1);
	for (i = n - 1; i >= 0; i--) {
		if (l[i] - r[i] < 0) {
			if (lrsum >= r[i]) {
				lrsum = lrsum + l[i] - r[i];
				flag[i] = 1;
			}
			else {
				cout << "No\n";
				return 0;
			}
		}
	}
	/*
	int ischanged;
	while (checker > 0) {
		ischanged = 0;
		for (i = n - 1; i >= 0; i--) {
			if (flag[i] == 0) {
				if (r[i] <= lrsum) {
					lrsum = lrsum + lr[i];
					flag[i] = 1;
					checker--;
					ischanged = 1;
				}
			}
		}
		if (ischanged == 0) {
			cout << "No\n";
			return 0;
		}
	}
	*/

	cout << "Yes\n";
	return 0;


	//以下Fの間違い
	/*cin >> n;
	int i, j;
	int lrsum=0;
	int l, r, rmax;
	for (i = 0; i < n; i++) {
		flag[i] = 0;
		cin >> s[i];
		l = 0;
		r = 0;
		rmax = 0;
		for (j = 0; j < s[i].length(); j++) {

			if (s[i][j] == '(') {
				l++;
			}
			else {
				r++;
				if (r - l > rmax) {
					rmax = r - l;
				}
			}

		}
		lr[i] = l - r;
		rdep[i] = rmax;
		//cout << lr[i] << rdep[i] << endl;
		lrsum = lrsum + lr[i];

	}
	if (lrsum != 0) {
		cout << "No\n";
		return 0;
	}
	//rmaxでソートする．
	//まずrmaxが0の奴を全部足し合わせる．一つもなければアウト．
	//次にrmaxがl-r以下のやつのなかから，できるだけlrが大きい順に足し合わせる．
	margesort(lr, n, 0, n - 1);

	//for (i = 0; i < n; i++) {
		//cout << rdep[i] <<  lr[i] << endl;
	//}
	int ncount = n;
	lrsum = 0;
	for (i = 0; i < n; i++) {
		if (rdep[i] == 0) {
			lrsum = lrsum + lr[i];
			flag[i] = 1;
			ncount--;
		}
	}
	//cout << lrsum;
	int checker;
	while (ncount > 0) {
		checker = 0;
		for (i = n - 1; i >= 0; i--) {
			if (flag[i] == 0) {
				if (lrsum >= rdep[i]) {
					lrsum = lrsum + lr[i];
					flag[i] = 1;
					ncount--;
					checker = 1;
				}
				else {
					//cout << "No\n";
					//return 0;
				}
			}
		}
		if (checker == 0) {
			cout << "No\n";
			return 0;
		}
	}
	cout << "Yes\n";
	return 0;
	*/
	/*string s, t;
	cin >> s;
	cin >> t;
	int i;
	for (i = 0; i < s.length(); i++) {
		if (s[i] == t[i]) {

		}
		else {
			cout << "No\n";
			return 0;
		}
	}

	cout << "Yes\n";
	return 0;*/

	/*int a, b, c, k;
	cin >> a >> b >> c >> k;
	if (k <= a) {
		cout << k << endl;
	}
	else if (k <= a + b) {
		cout << a << endl;
	}else{
		cout << a - (k - a - b) << endl;
	}
	return 0;*/
	/*cin >> n >> m >> x;
	int i,j;
	
	for (i = 0; i < n; i++) {
		cin >> c[i];
		for (j = 0; j < m; j++) {
			cin >> a[i][j];
		}
	}
	for (i = 0; i < m; i++) {
		un[i] = 0;
	}
	cout << dfs(un, 0, 0) << endl;
	return 0;*/
	/*
	cin >> n >> k;
	int i;
	for (i = 1; i <= n; i++) {
		cin >> a[i];
		flag[i] = 0;
	}
	long long int c = 1;
	flag[1] = 1;
	i = 1;
	long long int preloop;
	long long int looplength;
	while (1) {
		i = a[i];
		if (flag[i] > 0) {
			preloop = flag[i] - 1;
			looplength = c + 1 - flag[i];
			break;
		}
		else {
			c++;
			flag[i] = c;
		}
	}
	if (k > preloop) {
		k = ((k - preloop) % (looplength)) + preloop;
	}
	int j = 1;
	for (i = 0; i < k; i++) {
		j = a[j];
	}
	cout << j << endl;
	return 0;*/

}
/*int dfs(int u[], int k, int money) {
	//kを加えるのと加えないの．
	//cout << 'a\n';
	int i;
	int mmoney;
	int unn[12];
	int flag = 0;
	int money1, money2;
	mmoney = money + c[k];//kを買った場合のお金
	for (i = 0; i < m; i++) {
		unn[i] = u[i] + a[k][i];//理解度の追加
		if (unn[i] < x) {//理解が足りない
			flag = 1;
		}
	}
	if (k == n-1) {
		if (flag > 0) {
			return -1;
		}
		else {
			return mmoney;
		}
	}
	if (flag == 0) {
		money1 = mmoney;//そろったなら次から調べない．
	}
	else {
		money1 = dfs(unn, k + 1, mmoney);
	}
	money2 = dfs(u, k + 1, money);//kを買わない場合．
	if ((money1 == -1) && (money2 == -1)) {
		return -1;
	}
	else if (money1 == -1) {
		return money2;
	}
	else if (money2 == -1) {
		return money1;
	}
	else if (money2 < money1) {
		return money2;
	}
	else{
		return money1;
	}
}*/


void margesort(int a[], int a_len, int left, int right,int lr) {
	int i, j, mid, L, R;

	if (right <= left)
		return;

	mid = (left + right) / 2;
	margesort(a, mid, left, mid,lr);
	margesort(a, a_len - mid, mid + 1, right,lr);

	for (i = left; i <= mid; i++) {
		temp[i] = a[i];
		if (lr == 0) {
			tempb[i] = l[i];
		}
		else {
			tempb[i] = r[i];
		}
		tempc[i] = flag[i];
	}
	for (i = mid + 1, j = right; i <= right; i++, j--)
	{
		temp[i] = a[j];
		if (lr == 0) {
			tempb[i] = l[j];
		}
		else {
			tempb[i] = r[j];
		}
		tempc[i] = flag[j];
	}
	L = left;
	R = right;

	for (i = left; i <= right; i++)
	{
		if (temp[L] <= temp[R])
		{
			a[i] = temp[L];
			if (lr == 0) {
				l[i] = tempb[L];
			}
			else {
				r[i] = tempb[L];
			}
			flag[i] = tempc[L];
			L++;
		}
		else
		{
			a[i] = temp[R];
			if (lr == 0) {
				l[i] = tempb[R];
			}
			else {
				r[i] = tempb[R];
			}
				flag[i] = tempc[R];
			R--;
		}
	}
}