• Codeforces-1095E-Almost-Regular-Bracket-Sequence


    题意

    给定一个长度为 (n) 的小括号序列,求有多少个位置满足将这个位置的括号方向反过来后使得新序列是一个合法的括号序列。即在任意一个位置前缀左括号的个数不少于前缀右括号的个数,同时整个序列左右括号个数相同。

    分析

    括号序列显然采取前缀和思想,将('(')记做(1),将(')')记做(-1),记为(sum[])数组,并统计('(')的前缀和,即为(suml[])数组,统计(')')的前缀和,即为(sumr[])数组。

    可以发现,对于某一个序列,只能翻转('(')(')')一种类型,分类进行分析:

    ((1))('(')(')')(2)个,则翻转('(')可以使得(sum[n])变为(0)。考虑翻转第(i)位的('(')会产生的影响。对于(ileq jleq n)来说,所有的(sum[j])都减去(2),所以要保证所有的(sum[])都大于0,即找到(i),有

    • (1leq k <i),(sum[k]>=0)
    • (i < j leq n),(sum[j]>=2)
    • (sum[i]=1)

    答案即为(i)~(n)('(')数量。

    ((2))('(')(')')(2)个,可以通过翻转字符串并将所有的('(')(')')翻转获得第((1))种情况。也可以通过考虑翻转第(i)位的(')')会产生的影响,对于(ileq jleq n)来说,所有的(sum[j])都加上(2),所以要保证所有的(sum[])都大于0,即找到(i),有

    • (1leq k <i),(sum[k]>=0)
    • (i < j leq n),(sum[j]>=-2)
    • (sum[i]=-1)

    答案即为(1)~(i)中的(')')数量。

    ((3))其他情况输出(0)即可,存在已经为括号序列的字符串,也存在不可能满足条件的字符串。

    #pragma GCC optimize(3, "Ofast", "inline")
    
    #include <bits/stdc++.h>
    
    #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define ll long long
    #define LL long long
    #define int ll
    using namespace std;
    const int maxn = (ll) 1e6 + 5;
    const int mod = 1000000007;
    const int inf = 0x3f3f3f3f;
    int sum[maxn];
    int suml[maxn];
    int sumr[maxn];
    char s[maxn];
    
    signed main() {
        start;
        int n;
        cin >> n;
        cin >> (s + 1);
        for (int i = 1; i <= n; ++i) {
            suml[i] = suml[i - 1];
            sumr[i] = sumr[i - 1];
            if (s[i] == '(')
                sum[i] = sum[i - 1] + 1, ++suml[i];
            else
                sum[i] = sum[i - 1] - 1, ++sumr[i];
        }
        if (sum[n] == 2) {
            for (int i = 1; i <= n; ++i)
                if (sum[i] < 0) {
                    cout << 0;
                    return 0;
                }
            int l = n;
            for (; l > 0; --l)
                if (sum[l] == 1)
                    break;
            cout << suml[n] - suml[l];
        } else if (sum[n] == -2) {
            for (int i = 1; i <= n; ++i)
                if (sum[i] < -2) {
                    cout << 0;
                    return 0;
                }
            int l = 1;
            for (; l <= n; ++l)
                if (sum[l] == -1)
                    break;
            cout << sumr[l];
        } else
            cout << 0;
        return 0;
    }
    
  • 相关阅读:
    hdu5833----高斯消元
    高斯消元模板
    hdu4462--曼哈顿距离
    卡特兰数应用
    poj3070矩阵快速幂求斐波那契数列
    poj1042
    poj1328
    mvc 请求处理管道
    sql update 代替游标写法
    sql 表字段模糊连接
  • 原文地址:https://www.cnblogs.com/F-Mu/p/12050362.html
Copyright © 2020-2023  润新知