• CF1556 C. Compressed Bracket Sequence


    https://codeforces.com/problemset/problem/1556/C

    题意:

    给出一个描述左右括号个数的序列,例如2 3 4 3表示(()))(((()))

    问有多少个合法的连续子序列

    左括号为1,右括号为-1,统计前缀和

    一段区间[l,r]是合法的括号序列,满足2个要求

    1、任意位置前缀和>=0(以区间左端点为第一个位置)

    2、区间和=0

    我们把输入中的一个数字看作一段

    枚举奇数段,表示统计的子区间左端点所在段

    往后枚举右端点所在段

    奇数位置(表示左括号)直接加

    偶数位置(表示右括号),累计答案

    设枚举的奇数段有str个左括号,那么右端点所在段的前缀和只要出现[0,str]中的数,就可以满足区间和=0

    但是还有区间内任意位置前缀和>=0的要求

    当右端点枚举到偶数位置的段时,要记录到目前为止的右括号总数 减去 除去左端点所在段的左括号总数

    每次累计答案都用到目前为止记录的最大值mx

    这样相当于算出了一个要从第一段的后面用多少个左括号补中间的缺少,剩下的才是可以用于抵消当前右端点所在段的左括号

    所以当前右端点的前缀和要出现在[0,str-mx]中

    最后注意前缀和<0时要停止,换下一个左端点段

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define N 1003
     
    int a[N];
     
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i) 
        {
            scanf("%d",&a[i]);
            if(!(i&1)) a[i]=-a[i];
        }
        long long ans=0,pre=0,stl,tmp,mx,str,l,r;
        for(int i=1;i<=n;i+=2)
        {
            pre=a[i];
            str=a[i];
            tmp=mx=0;
            for(int j=i+1;j<=n;++j)
            {
                if(j&1) 
                {
                    pre+=a[j];
                    tmp-=a[j];
                }
                else
                {
                    r=pre-1;
                    l=pre+a[j];
                    ans+=max(0ll,min(r,str-mx)-max(0ll,l)+1ll);
                    pre+=a[j];
                    tmp-=a[j];
                    mx=max(mx,tmp);
                    if(pre<0) break;
                }
            }
        //    printf("%d
    ",ans);
        }
        printf("%lld",ans);
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    django缓存机制
    RBAC基于角色访问控制
    Book系列十大接口
    xadmin的使用
    JWT认证
    自动生成接口文档
    drf的过滤排序分页异常处理
    认证权限解析频率
    python学习之内置模块补充
    python学习之内置模块补充作业
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15235939.html
Copyright © 2020-2023  润新知