D. Bracket Coloring

题目链接:Problem - 1837D - Codeforces

题意理解:

判断是否可以将字符串s分成若干字子串,使每个子串或每个翻转的子串是合法的括号序列。

预备知识:

首先要知道如何判断一个括号序列是否是合法,共有两个条件:

1.左括号数=右括号数

2.对于任意位置i,i前的左括号数一定大于等于右括号数(即右括号数不大于左括号数)

解题思路:

这个字符串最终一定会分为两个部分,一部分是不翻转就合法的,另一部分是需要翻转才合法的(每部分都可能为空)。

思路一:

首先判断整个字符串是否是一个合法的括号序列,如果他不是,输出-1;

对于每一个位置,那么如果前面左括号多,那么将它放到无需翻转的子串中,否则,放到需要翻转的子串中。

但是感觉这种思路的合理性证明不好解释,又用了思路二。

代码:

#include
using namespace std;

int T,n;
string s;
int ans[200005];

bool check()
{
    int l=0,r=0;
    for(int i=0;i>n>>s;

    //先进行合法性检验
    if(!check())
    {
        cout<<"-1"<=r) ans[i]=1;
            else ans[i]=2;
            l++;
        }
        else
        {
            r++;
            if(l>=r) ans[i]=1;
            else ans[i]=2;
        }
    }

    int cnt=1;
    for(int i=1;i>T;
    while(T--)
    {
        solve();
    }

    return 0;
}

思路二:

首先判断这个序列1.是否合法?2.是否可以用一种颜色填充。

合法:左括号数等于右括号数

一种颜色填充:保证任意位置左括号数始终大于右括号数(整个字符串是一个合法括号序列) 或者 保证任意位置右括号数始终大于左括号数(将整个字符串翻转,是一个合法括号序列)

否则,他就一定需要两种颜色填充。

那么就要找一个最长合法子串,开一个栈S,对于每个位置:

如果是左括号,那么就直接压进去;

如果是右括号,那么判断栈顶是否为左括号,如果是左括号,那么就与栈顶的左括号匹配,一起出栈;否则,他前面就没有左括号了,他就是需要翻转位置。

到最后,栈一定是栈顶都是左括号,栈底都是右括号,如:“)))(((”这样的形式。

将这些位置填充为颜色2

代码:

#include
#include
using namespace std;

const int N = 200005;
int n,T;
string s;
int ans[N];
stackS;

void solve()
{
    cin>>n>>s;

    //先判断两个问题:1.是否合法    2.是否可以用一种颜色填充
    int l=0,r=0;
    bool sv1=true,sv2=true;
    for(int i=0;il) sv1=false;
        if(l>r) sv2=false;
    }

    if(l!=r)
    {
        cout<<"-1"<>T;
    while(T--) solve();

    return 0;
}

你可能感兴趣的:(cf,算法)