JZOJ 4209. 【五校联考1day1】已经没有什么好害怕的了

题目

 

 

Description

小Y 最近开始学习算法姿势,但是因为小R 非常BB,给了她很多B6 题,所以她觉得自己已经没有什么前途了。于是小R 给了她一些稍微简单的题,让她觉得已经没有什么好害怕的了,其中一道是这样的:
给定一个长度为n 只包含左括号和右括号的序列,现在小R 想要知道经过每一个位置的合法子串有多少个。
空串是一个合法的串,如果A 和B 都是合法的串,那么(A) 和AB 都是合法的串。
 

Input

第一行输入一个正整数T 表示数据组数。接下来T 行每行一个字符串。

Output

对于每组数据,输出一个整数表示答案,令ansi 为经过第i 个位置的子串个数,那么你需要输出(注意是先求余再求和)
 

Sample Input

1
()()

Sample Output

20
样例解释:
ans 数组为{2,2,2,2},所以输出20。
 

Data Constraint

对于10% 的数据,n<=100
对于30% 的数据,n <= 1000
对于60% 的数据,n <= 5 <= 10^4
对于100% 的数据,n <= 10^6,1 <= T<= 10

分析

          考场的时候,根本没有看懂题目 zzz,出题人有毒

        这道题的正解其实是一个差分数组的思想

        将左括号的位置指向离他最近的有括号后面

        左右各算一遍,相加就能得到一个差分数组

        得到前缀和,算出答案即可

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #define mo 1000000007
 7 #define N 1000005
 8 using namespace std;
 9 int a[N],l[N],r[N],le[N],ri[N],len=0;
10 char s[N];
11 long long ans=0,f[N];
12 void fillchar()
13 {
14     fill(a,a+N,0);
15     fill(l,l+N,0);
16     fill(r,r+N,0);
17     fill(le,le+N,0);
18     fill(ri,ri+N,0);
19     ans=0;
20 }
21 int main()
22 {
23     int T;
24     scanf("%d",&T);
25     while (T--)
26     {
27         fillchar();
28         int tot=0;
29         scanf("%s",s+1);
30         len=strlen(s+1);    
31         for (int i=1;i<=len;i++)
32         if (s[i]=='(') a[++tot]=i;
33         else 
34         if (tot!=0) 
35         {
36                le[a[tot]]=i+1;
37                 ri[i+1]=a[tot--];
38         }
39         for (int i=len+1;i>=1;i--)
40         {
41             r[i]++;
42             r[ri[i]]+=r[i];
43         }
44         for (int i=1;i<=len;i++)
45         {
46             l[i]--;
47             l[le[i]]+=l[i];
48         }
49         for (int i=1;i<=len;i++) 
50             f[i]=r[i]+l[i];
51         for (int i=1;i<=len;i++) 
52             f[i]+=f[i-1];
53         for (int i=1;i<=len;i++) 
54             ans=ans+i*f[i]%mo;
55         printf("%lld\n",ans);
56     }
57 }

 

posted @ 2019-01-21 20:41  Melted_czj  阅读(248)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色