• Codeforces 990C (模拟+组合数学)


    题面:

    传送门

    分析:

    此题O(n2l)模拟肯定是会超时的(l为所有字符串总长)
    我们想到对字符串进行一定的预处理,可以快速计算匹配
    我们设每一个(的值为1,)的值为-1,规定
    若只有)括号多了x个,则l[i]=r[i]=-x<0
    若只有(括号多了x个,则l[i]=r[i]=x>0
    那么如何求l[i],r[i]的值呢?
    从左到右扫描字符串,用一个变量cnt,统计和
    cnt的最小值=l[i],最终的值=r[i]
    若(和)都有多余,则必须接两个字符串,不符合条件,所以计算时应该直接跳过这些字符串,不用考虑

    要理解这句话,请看下面的模拟过程
    )()
    字符串下标(0开始) 0 1 2
    cnt值 -1 0 -1
    l[i]=-1,说明左边需要一个(括号来匹配 (>=0即不需要)
    r[i]=-1,说明右边不需要(<=0即不需要),而左边需要一个(括号

    我们以all[i]来hash,哈希表的第 x位存储了所有r[i]=x的字符串的l[i]
    但要注意的是,由于负数的原因,数组下标要人为加上一个数addv来存储

    为了防止一对字符串被算两次,我们规定字符串只能接在右边,我们枚举字符串时要先保证l[i]>=0才能接,而l[i]<0的只能接在其他字符串右边
    对于一个l[i]>=0的字符串i,我们寻找接在它右侧能匹配的字符串,所以我们在哈希表的r[i]位置寻找l[i]值为r[i]的字符串

    比如:()(的l[i]=0,r[i]=1,我们则要寻找r[i]=l[i]=-1,即只多了一个)括号的字符串

    用二分查找统计值为r[i]的字符串的个数,答案+=值为r[i]的字符串的个数
    预处理时间复杂度O(l) (l为所有字符串总长)
    二分查找时间复杂度O(nlog2l)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector> 
    #include<algorithm>
    #define addv 300005
    #define maxn 2*addv
    using namespace std;
    int n;
    char str[maxn];
    int cnt;
    int l[maxn];
    int r[maxn];
    vector<int>table[maxn];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",str);
            int len=strlen(str);
            l[i]=maxn;
            cnt=0;
            for(int j=0;j<len;j++){//像分析中一样求l[i],r[i]
                if(str[j]=='(') cnt++;
                else cnt--;
                l[i]=min(l[i],cnt);
            }
            r[i]=cnt;
            table[r[i]+addv].push_back(l[i]);//hash,为了防止负数人为加上addv,addv就相当于新的零点
        }
        for(int i=1;i<maxn;i++) if(table[i].size()!=0) sort(table[i].begin(),table[i].end());//排序,为了二分查找
        long long ans=0;
        for(int i=1;i<=n;i++){
            if(l[i]>=0){
                int tmp=addv-r[i];//即-r[i]
                ans+=table[tmp].end()-lower_bound(table[tmp].begin(),table[tmp].end(),-r[i]);//lower_bound返回第一个>=x的位置,用结尾去-它,可求出l[j]=r[j]=-r[i]的j的个数
            }
        }
        printf("%I64d
    ",ans);
    } 
  • 相关阅读:
    Windows控制台程序“选定模式”的问题
    落网的音乐很好听的,你造么?不能下载啊,怎么破?
    记一次复杂的正则匹配——匹配但不包含
    判断浏览器是否为IE内核的最简单的方法
    Nodejs发送Post请求时出现socket hang up错误的解决办法
    Windows下通过bat脚本实现自动上传文件到ftp服务器
    jQuery对html进行Encode和Decode
    scala学习笔记:理解类继承
    scala学习笔记:理解lazy值
    scala学习笔记:match表达式
  • 原文地址:https://www.cnblogs.com/birchtree/p/9845835.html
Copyright © 2020-2023  润新知