构造
永远做不出来的构造题。直接贴聚聚的题解了(逃
题目大意
给定一个字符串,仅由0和1组成,长度为n。你需要给出两个合法的括号序列,它们的长度为n。并且满足:如果字符串的第n位为1,则这两个括号序列的第n位相同。如果字符串的第n位为0,则这两个括号序列的第n位相反。如果不存在这样的括号序列,输出NO。
作者:mutsuki1
https://www.bilibili.com/read/cv10616355/
出处: bilibili
解题思路
首先,合法的括号序列必须由’(‘开始,到’)‘结束。所以字符串开头和结尾必须都为1。然后,0的个数必须为偶数,否则两个序列的’(‘和’)'的数量肯定不同,导致肯定有一个序列不合法。最后就是如何构造的问题。
一个比较简单的方法是,对字符串的前n/2个1,两个括号序列的对应位置都是’(’。对字符串的后n/2个1,两个括号序列的对应位置都是’)’。
对字符串的第奇数个0,两个括号序列的对应位置是’(‘和’)’。对字符串的第偶数个0,两个括号序列的对应位置是’)‘和’(’。
举几个例子:
10000001
( ()()() )
( )()()( )
从上面这个例子也可以很容易的理解为什么必须有偶数格0。
11111111
( ((())) )
( ((())) )
理解了这两个例子,那么对一个0和1都有的字符串,我们只要按这个规律处理就可以了。
10110001
( (())() )
( )()()( )
作者:mutsuki1
https://www.bilibili.com/read/cv10616355/
出处: bilibili
参考代码
#include<bits/stdc++.h>
//#define LOCAL //提交时一定注释
#define VI vector<int>
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef double db;
const int inf = 0x3f3f3f3f;
const LL INF = 1e18;
const int N = 100 + 10;
const LL mod = 1e6 + 7;
#define ls rt << 1
#define rs rt << 1 | 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
inline int readint() {int x; scanf("%d", &x); return x;}
int cnt[N];
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int t = readint();
while(t--) {
int n = readint();
string s; cin >> s;
bool ok = true;
if (s[0] != '1' || s.back() != '1') ok = false;
int cnt0 = 0;
for(auto k : s) {
if (k == '0') cnt0++;
}
int cnt1 = n - cnt0;
if (cnt0 & 1) ok = false;
if (!ok) {
printf("NO\n"); continue;
}
printf("YES\n");
int p1 = 0, p0 = 0;
for(auto k : s) {
if (k == '0') {
p0++;
printf("%c", (p0 & 1) ? '(' : ')');
}
else {
p1++;
printf("%c", (p1 <= cnt1 / 2) ? '(' : ')');
}
}
printf("\n");
p1 = 0, p0 = 0;
for(auto k : s) {
if (k == '0') {
p0++;
printf("%c", (p0 & 1) ? ')' : '(');
}
else {
p1++;
printf("%c", (p1 <= cnt1 / 2) ? '(' : ')');
}
}
printf("\n");
}
return 0;
}