【构造】Codeforces Round #712 (Div. 2) C. Balance the Bits

构造

永远做不出来的构造题。直接贴聚聚的题解了(逃

C. Balance the Bits

题目大意

给定一个字符串,仅由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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值