zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Linux
    Linux -- 文件统计常用命令
    再论最小二乘
    再论EM算法的收敛性和K-Means的收敛性
    【MySQL】优化—工欲善其事,必先利其器之EXPLAIN
    【Linux】浅谈段页式内存管理
    【Linux】之系统工具top
    【Linux】之shell特殊变量整理
    【Linux】系统 之 RAID
    【MySQL】binlog缓存的问题和性能
  • 原文地址:https://www.cnblogs.com/F-Mu/p/12050362.html
Copyright © 2011-2022 走看看