cf的构造题果然不会让人失望
虽然我写不出来,但是这道题仍然很有意思。
题意
构造两个合法的括号序列,使得这两个括号序列第 ii 个字符相同当且仅当 a i = 1 a_i =1 ai=1。
看到题意之后果断进行一个模拟,发现了若 a 1 = 0 ∣ ∣ a n = 0 ∣ ∣ n & 1 ∣ ∣ z e r o & 1 a_1=0 || a_n= 0 || n \&1||zero\&1 a1=0∣∣an=0∣∣n&1∣∣zero&1,那么必定无解。
然后就开始瞎写了
我们仍然需要一个合理且有条理的思路。比较容易想到的是我们应该对 a i = 1 a_i=1 ai=1的位置先填数。填什么数又是一个问题。
这是我们想到之前确定了 a 1 ! = 1 & & a n ! = 1 a_1 != 1 \&\& a_n !=1 a1!=1&&an!=1 那么这两个位置填什么就确定了,然后试着前一半后一半分别填"(“和”)",那么我们就得到了第一步目前为止正确的序列。剩下的是为0也就是两串不同的位置。
我们又可以猜测,对于一个已经合法的括号序列,插入一个合法的括号序列仍合法,因为剩下的正好是偶数,对于每一个没填的位置我们直接分别插入两个不同符号,最后输出几组样例看一下,做法无误。(归根究底一直在猜)
#include "bits/stdc++.h"
using namespace std;
#define int long long
const int N = 3e5 + 100;
int a[N];
char s1[N];
char s2[N];
void solve() {
int T;
cin >> T;
while (T--) {
memset(s1, 0, sizeof s1);
memset(s2, 0, sizeof s2);
int n;
cin >> n;
int f = 0;
int ze = 0;
for (int i = 1; i <= n; ++i) {
char tt;
cin >> tt;
int t = tt - '0';
a[i] = t;
if (t == 0 && (i == 1 || i == n)) f = 1;
if (t == 0) ze++;
}
if (f || (ze & 1) || n & 1) {
cout << "NO" << endl;
} else {
int on = n - ze;
for (int i = 1; i <= n; ++i) {
if (a[i] == 1) {
if (on > (n - ze) / 2)
s1[i] = s2[i] = '(';
else s1[i] = s2[i] = ')';
on--;
}
}
int t = 0;
for (int i = 1; i <= n; ++i) {
if (s1[i] == 0) {
s1[i] = t == 0 ? '(' : ')';
s2[i] = t == 0 ? ')' : '(';
t ^= 1;
}
}
cout << "YES" << endl;
cout << s1 + 1 << endl;
cout << s2 + 1 << endl;
}
}
}
signed main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}