cf 990c(思维+括号匹配)

  题目大意就是给你n个括号序列,然后问si+sj组成的序列能完美匹配,这样的(i,j)的个数是多少。

  首先可以知道自身就是完美匹配的括号序列(假设数量为x)对答案的贡献为x^2,因为每一个自身就是完美匹配的括号序列可以和其本身或其他的自身就是完美匹配的括号序列组成一个符合条件的序列。然后其次对一个序列去掉了已经匹配的括号之后,剩下的括号里既有左括号又有右边括号的话是对答案没有贡献的,因为这样的括号序列不可能和任何一个括号序列组成一个可以完美匹配的括号序列,接着对一个序列去掉了已经匹配的括号之后,剩下的括号里只有左括号或者右括号的话是对答案有贡献的,设le[i]表示去掉已匹配的括号后剩下i个左括号的序列的个数,ri[i]表示去掉已匹配的括号后剩下i个右括号的序列的个数,那么对答案的贡献就是le[i]*ri[i]。那么就很明显了算一个x,le数组,ri数组就好了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
#define ll long long
ll le[maxn]={0},ri[maxn]={0};
ll tmp=0,ans=0;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        char s[maxn];
        int num1=0,num2=0;
        stack<char>st;
        while(!st.empty()) st.pop();
        scanf("%s",s);
        for(int i=0;s[i]!=0;i++)
        {
            if(st.empty())
            {
                st.push(s[i]);
            }
            else
            {
                char ch=st.top();
                if(ch=='('&&s[i]==')')
                    st.pop();
                else
                {
                    st.push(s[i]);
                }
            }
        }
        if(st.empty())
            tmp++;
        else
        {
            while(!st.empty())
            {
                char ch=st.top();
                st.pop();
                if(ch==')')
                    num1++;
                else
                    num2++;

            }
            if(num1!=0&&num2!=0)
                continue;
            else
                if(num1!=0)
                {
                    le[num1]++;
                }
                else
                    ri[num2]++;
        }

    }
    ans+=tmp*tmp;
    for(int i=1;i<=maxn-10;i++)
        ans+=le[i]*ri[i];
    printf("%lld
",ans);
    return 0;

}
原文地址:https://www.cnblogs.com/eason9906/p/11754890.html