Codeforces Round #459 (Div. 2) C. The Monster

题目链接:C. The Monster

题目大意

给你一个括号序列,包括()?三个字符,其中?可以代替()中的任意一个,求有多少区间[L, R],使得[L, R]是合法的括号序列。

思路

判断一个括号序列是否合法,必须保证(和)的数量相等,并且从左往右的过程中,)的数量一定一直小于等于(的数量,否则多余的)之后永远无法匹配。
从左往右判断一遍,如果)的数量大于(和?的数量,说明之后那个多余的)再也无法消除了,剩下的都不合法,这时直接break;再从右往左同样地判断一遍,两遍都符合条件的区间就是合法的,++ans。

代码

GNU C++14 Accepted 156 ms 142800 KB

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;

const int maxn = 6000;
char s[maxn];
int c[maxn][maxn];

int main()
{
    cin >> s;
    int len = strlen(s);
    int ans = 0;
    for(int l=0; l<len; ++l)
    {
        int cnt[3] = {0, 0, 0};
        for(int r=l; r<len; ++r)
        {
            if(s[r] == '(') ++cnt[0];
            else if (s[r] == ')') ++cnt[1];
            else ++cnt[2];
            if(cnt[1] > cnt[0]+cnt[2]) break;
            int x = abs(cnt[0]-cnt[1]);
            if(x<=cnt[2] && (cnt[2]-x)%2==0) c[l][r]++;
        }
    }
    for(int r=len-1; r>=0; --r)
    {
        int cnt[3] = {0, 0, 0};
        for(int l=r; l>=0; --l)
        {
            if(s[l] == '(') ++cnt[0];
            else if (s[l] == ')') ++cnt[1];
            else ++cnt[2];
            if(cnt[0] > cnt[1]+cnt[2]) break;
            int x = abs(cnt[0]-cnt[1]);
            if(x<=cnt[2] && (cnt[2]-x)%2==0) c[l][r]++;
            if(c[l][r] == 2) ++ans;
        }
    }
    cout << ans << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/litmxs/article/details/79204934