Educational Codeforces Round 45 (Rated for Div. 2) C. Bracket Sequences Concatenation Problem

C. Bracket Sequences Concatenation Problem

A bracket sequence is a string containing only characters "(" and ")".

A regular bracket sequence is a bracket sequence that can be transformed into a correct arithmetic expression by inserting characters "1" and "+" between the original characters of the sequence. For example, bracket sequences "()()", "(())" are regular (the resulting expressions are: "(1)+(1)", "((1+1)+1)"), and ")(" and "(" are not.

You are given nn bracket sequences s1,s2,,sns1,s2,…,sn. Calculate the number of pairs i,j(1i,jn)i,j(1≤i,j≤n) such that the bracket sequence si+sjsi+sj is a regular bracket sequence. Operation ++ means concatenation i.e. "()(" + ")()" = "()()()".

If si+sjsi+sj and sj+sisj+si are regular bracket sequences and iji≠j, then both pairs (i,j)(i,j) and (j,i)(j,i) must be counted in the answer. Also, if si+sisi+si is a regular bracket sequence, the pair (i,i)(i,i) must be counted in the answer.

Input

The first line contains one integer n(1n3105)n(1≤n≤3⋅105) — the number of bracket sequences. The following nn lines contain bracket sequences — non-empty strings consisting only of characters "(" and ")". The sum of lengths of all bracket sequences does not exceed 31053⋅105.

Output

In the single line print a single integer — the number of pairs i,j(1i,jn)i,j(1≤i,j≤n) such that the bracket sequence si+sjsi+sj is a regular bracket sequence.

Examples
input
Copy
3
)
()
(
output
Copy
2
input
Copy
2
()
()
output
Copy
4

题意:给你n行括号序列,从中任选两个序列i,j,进行配对,如果i,j合二为一新序列括号完全匹配,即配对成功。同时i,j和j,i认为是两种方案,且i==j可取。问你最终配对方案总数。

思路:在解决本题之前,先介绍一个括号配对题的处理技巧,可以很容易的把问题转化为数字问题,非常实用。接下来描述的括号序列中都只含有‘(’‘)’。

任给一个括号序列s,我们应该立即得出:使得s完全匹配时,还需要左括号个数l,右括号个数r。

简单说明一下思路:令l=r=0,自左至右扫描序列,遇到‘(’则l++。当遇到‘)’时,有左括号肯定要利用的嘛,当l>0,l--,否则r++。

for(ll i=1;i<=len;i++)
{
    if(s[i]=='(')l++;
    else
    {
        if(l>0)l--;
        else r++;
    }
}

所得的l,r就是使序列s自身刚好匹配时,还需的左右括号数,这个结论对于一般的括号问题,都能有效的转化成统计数字的问题。

现在我们来看本题,选出两个进行接合,那么接合时,有一端必然是空着的,因此如果l,r都大于0,此时无论怎样都不可能配对的,这种序列直接丢掉就行了,然后预处理l>0,r==0的,map[l]++统计。之后l==0,r>0,可以发现当l==r时,匹配成功。这样我们就把括号序列问题转化为了数字匹配问题。

最后要注意,l=r=0的情况,此时把所有0单独处理,假设有x个0,匹配总数=C[x,2]*2+x=x^2。乘2即i,j  j,i的情况。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#define ll long long
#define exp 1e-8
#define mst(a,k) memset(a,k,sizeof(a))
#define pi acos(-1.0)
using namespace std;
map<ll,ll>mp;
ll n,a[300030];
char s[300030];
int main()
{
    while(~scanf("%lld",&n))
    {
        mp.clear();
        for(ll i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            ll len=strlen(s+1),l=0,r=0;
            for(ll i=1;i<=len;i++)   //统计l,r
            {
                if(s[i]=='(')l++;
                else
                {
                    if(l>0)l--;
                    else r++;
                }
            }
            if(l&&r)   //转化成数字记录在数组中
            {
                i--;
                n--;
                continue;
            }
            else if(l) a[i]=l;
            else a[i]=-r;   //我把r保存成负数了,实现l+r==0,其实不用
        }
        ll zero=0;
        for(ll i=1;i<=n;i++)   //先统计l
        {
            if(a[i]>0)mp[a[i]]++;
            if(a[i]==0)zero++;
        }
        ll ans=0;
        for(ll i=1;i<=n;i++)   //现在是r
        {
            if(a[i]<0)
            {
                a[i]*=-1;
                if(mp[a[i]])
                {
                    ans+=mp[a[i]];
                }
            }
        }
        ans+=zero*zero;   //把所有0单独处理,公式就是组合数推导一下就行了
        printf("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值