CodeForces - 1503A Balance the Bits(括号序列+构造)

题意:

给出一个01串 s s s,要求构造出长度为 n n n(偶数)的两个合法的括号序列 s 1 s1 s1, s 2 s2 s2,满足:

1. 1. 1. s [ i ] = 1 s[i]=1 s[i]=1 , s 1 [ i ] = s 2 [ i ] s1[i]=s2[i] s1[i]=s2[i]

2. 2. 2. s [ i ] = 0 s[i]=0 s[i]=0, s 1 [ i ] ! = s 2 [ i ] s1[i]!=s2[i] s1[i]!=s2[i]

题解:

不擅长构造,更不擅长括号序列,好家伙,直接结合在一起。。。

解括号序列的题基本上都要想到这几点,很大程度上是解题的关键:

1. 1. 1. 左括号的数量=右括号的数量

2. 2. 2. 每个位置的前缀左括号数量必须要 ≥ \geq 前缀右括号数量。

进入正题:

合法的括号序列的首必须要是 ( ( ( ,尾必须是 ) ) ) ,因此必须 s [ 1 ] = s [ n ] = 1 s[1]=s[n]=1 s[1]=s[n]=1 ,因为 n n n 为偶数 ,所以左括号的数量必须等于右括号。 设 s 1 s1 s1 0 0 0 位置有 x x x个左括号和 y y y个右括号 , 那么1位置就有 n / 2 − x n/2-x n/2x个左括号, n / 2 − y n/2-y n/2y个右括号。那么 s 2 s2 s2中左括号的数量为 n / 2 − x + y n/2-x+y n/2x+y ,因为左括号数量等于 n / 2 n/2 n/2 ,所以 n / 2 − x + y = n / 2 n/2-x+y=n/2 n/2x+y=n/2 ,所以 x = y x=y x=y ,也就是说0位置一半是左,一半是右,1位置也是一半是左,一半是右,那么 1 1 1的数量就必须是偶数。上面就是能构造出答案的必要条件,否则就是 N O NO NO.

再来看怎么构造答案:

对于 1 1 1的位置,因为不会发生改变,而且正好需要一半左括号,一半又括号,所以只需把前半部分全都设为左括号,右半部分都设为右括号即可。

对于 0 0 0的位置,要尽可能的使每个位置左括号和右括号的差值 ≥ 0 \geq 0 0,那么可以交替构造,( ) ( ) ( )…

这样翻转后,因为开头保证了有一个左括号,所以依旧满足。

代码:

#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=2e5+5;
const int inf=0x3f3f3f3f;
char s[MAXN];
char ans1[MAXN],ans2[MAXN];
int main()
{   
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        cin>>s+1;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]=='1')
            {
                cnt++;
            }
        }
        if(cnt&1||s[1]=='0'||s[n]=='0')
        {
            printf("NO\n");
            continue;
        }
        int flag=0;
        cnt/=2;
        for(int i=1;i<=n;i++)
        {
            if(s[i]=='1')
            {
                if(cnt)
                {
                    ans1[i]=ans2[i]='(';
                    cnt--;
                }
                else 
                {
                    ans1[i]=ans2[i]=')';
                }
            }
            else
            {
                if(!flag) 
                {
                    ans1[i]='(';
                    ans2[i]=')';
                }
                else 
                {
                    ans1[i]=')';
                    ans2[i]='(';
                }
                flag^=1;
            }
        }
        printf("YES\n");
        for(int i=1;i<=n;i++)
        {
            printf("%c",ans1[i]);
        }
        printf("\n");
        for(int i=1;i<=n;i++)
        {
            printf("%c",ans2[i]);
        }
        printf("\n");
    }
}
posted @ 2021-04-18 00:18  TheBestQAQ  阅读(70)  评论(0)    收藏  举报