https://codeforces.com/contest/1504/problem/C
觉得大佬讲得很好:引自@mutsuki
合法括号序列也就是无论何时 '('的出现次数次数总≥')'
把括号和括回理解为分数 括号得一分 括回扣一分。目标是使任何时候两个序列的分数都>=0。这么构造可以使两个序列交替加分和扣分,从而满足条件。
而如果原本构造成一个合法,由于有0的存在,必然会导致原来的有一个地方不合法。需要纠正回来那么就要偶数个0.
@https://codeforces.com/profile/drayc
Imagine a 2d plane where (x,y) = (no. of unclosed open brackets in first sequence, no. of unclosed open brackets in second sequence). We can then map the 4 possible moves:
-> adding a '(' to first string when s[i]=1 => we go from x,y to x+1,y+1
-> adding a '(' to first string when s[i]=0 => we go from x,y to x+1,y-1
.. and similarly for adding ')' in both cases, we get opposite moves.
We start at origin, and our objective is to return to the origin after n moves without crossing any of the axes. If you draw it out on paper or something, it will be clear that by following the given strategy, we either stay on the x = y line or x = y + 1 line, and dont cross any of the axes, unless the string begins or ends with a 0.
考虑构造:两端首先要1.
其次将前n/2个1定义为'(',后n/2个1定义为')’;
由于加一分扣一分,那么对于0我们按其出现的奇偶次数分别给予'('/')'
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
char str[maxn];
char p[maxn];
char v[maxn];
int main(void){
cin.tie(0);std::ios::sync_with_stdio(false);
LL t;cin>>t;
while(t--){
LL len;cin>>len;
cin>>(str+1);
LL n=strlen(str+1);
if((n&1)||(str[1]=='0')||(str[n]=='0')){
cout<<"NO"<<"\n";
continue;
}
LL cnt=0;
for(LL i=1;i<=n;i++) if(str[i]=='1') cnt++;
LL num=1;LL flag=0;
for(LL i=1;i<=n;i++){
if(str[i]=='1'&&num<=cnt/2){
num++;
v[i]='(';
}
else if(str[i]=='1'&&num>cnt/2){
num++;
v[i]=')';
}
else if(str[i]=='0'&&(!flag)){
v[i]='(';flag^=1;
}
else if(str[i]=='0'&&(flag)){
v[i]=')';flag^=1;
}
}
for(LL i=1;i<=n;i++){
if(str[i]=='1') p[i]=v[i];
else{
if(v[i]=='(') p[i]=')';
else if(v[i]==')') p[i]='(';
}
}
stack<char>s;
for(LL i=1;i<=n;i++){
if(!s.empty() ){
if(s.top()=='('&&p[i]==')'){
s.pop();
}
else s.push(p[i]);
}
else s.push(p[i]);
}
if(!s.empty()){
cout<<"NO"<<"\n";
}
else{
cout<<"YES"<<"\n";
for(LL i=1;i<=n;i++){
cout<<v[i];
}
cout<<"\n";
for(LL i=1;i<=n;i++){
cout<<p[i];
}
cout<<"\n";
}
}
return 0;
}