Codeforces Round #712 (Div. 2)C. Balance the Bits


原题传送门

题目大意

给你一个01串,询问是否存在满足下列条件的两个合法括号串:
对与两个串在同一位置上,如果在该位置上01串是0,则代表这两个串在该位置上不同,而1则代表相同。
如果有,输出"YES"并且输出任意一对满足条件的串,如果没有则输出"NO"。

分析

在打这场的时候脑抽了
这是一道构造题,我们需要构造合法的串,如果存在的话。对此,我们需要先分析是否存在合法串,这是解决本题的第一步。由于题目给定的n是偶数,所以我们就不需要考虑奇数了。我们先考虑一个串作为原串,我们可以构造出很多个合法的括号串,但是考虑到这个串与另一个串的联系,并不是每一个合法串都会存在一个对应的合法串满足题意。
我们分析01串的影响,对于1来讲则代表这两个串在这些位置上相同,所以它的影响我们可以暂且认为是无;对于0来讲,则代表这个位置出现了异常,一个’(‘会变成’)’,一个’)‘会变成’(’,那么它的具体影响呢?
考虑一个合法的括号串,例如"()()()",如果3位置上为0,则另一个串会变成”()))()",发现没有?一个括号被拆掉了,并且多了一个无用的’)’,也就是说我们如果只有一个0,那么一定会破坏一个括号,那么则是无解。
我们接着把这个结论推广,如果是2个,我们可以通过破坏另一个之前被破坏的抵消掉,只需要对原创稍微改动,就一定可以做到,同理可以推广到0的个数为偶数则与2同理,为奇数,则与1同理。
为奇数显然无解,为偶数,我们又要怎么构造呢(这样一定有解)?
思考一个合法括号串的条件,首先必然是左括号和右括号数量相同,这是显然得,其次,如果我们从左往右看,则对于每一个’)’,前面必然有一个’(‘对应,也就是说,到目前这个位置为止,左括号数量必须要大于等于右括号。
这样的话,我们只需要贪心的去构造就可以了,一对一对的构造。
由于第一位和最后一位一定是相同的,否则无解(显然),这个判断一下。
然后对于第一个串,如果遇到1则先放’(’,下次放’)'依次类推,我们可以假设第一个括号和最后一个匹配,那么对于第一个串,只要中间部分满足上述条件即可,同样,对于0,也只要先左括号,再右括号,那么第一个必然合法,且第二个串也合法,因为第二个串,一开始已经有了一个左括号,对于1来讲根第一个串一样,对于0来讲,如果先右括号再左括号,一样有解。

//#include<bits/stdc++.h> ----万能头----
#include <iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<cmath>
#include<queue>
#include<list>
#include<map>
#include<unordered_map>
#include<stack>
using namespace std;
const int p = 1e9+7;
const int N = 2e5+5;
const int maxn = 1e5+10;
const long long INF = 1e17;
#define REP(i,n) for(int i = 1; i <= n; ++i)
#define REPA(i,j,n) for(int i = j; i <= n; ++i)
#define RREP(i,n) for(int i = n; i >= 1; --i)
#define REPR(i,j,n) for(int i = n; i >= j; --i)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> PII;
ll n, m, t, k;
char s[N],s2[N];
ll a[N];
ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char ans1[N],ans2[N];
void solve(){
    cin>>n;
    cin>>s+1;
    if(s[1] == '0'||s[n]=='0'){
        cout<<"NO"<<'\n';
        return;
    }
    bool f = 1;
    for(int i = 1;i <= n; ++ i){
        if(s[i]=='0')f^=1;
    }
    if(!f){
        cout<<"NO"<<'\n';
        return;
    }
    ans1[1] = ans2[1] = '(';
    ans1[n] = ans2[n] = ')';
    ans1[n+1] = ans2[n+1] = '\0';
    bool f1 = 0, f2 = 0;
    for(int i = 2;i < n ;++i){
        if(s[i] == '1'){
            if(f1)ans1[i] = ans2[i] = ')';
            else ans1[i] = ans2[i] = '(';
            f1 ^= 1;
        }
        else {
            if(f2){
                ans1[i] = ')';
                ans2[i] = '(';
            }
            else {
                ans1[i] = '(';
                ans2[i] = ')';
            }
            f2 ^= 1;
        }
    }
    cout<<"YES"<<'\n';
    cout<<ans1+1<<'\n';
    cout<<ans2+1<<'\n';
}


int main() {
    //ios::sync_with_stdio(0);
    //cin.tie(0);
    //cout.tie(0);

    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    scanf("%lld",&t);
    while(t--)
        solve();

    fclose(stdin);
    fclose(stdout);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值