• 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
    ",ans);
    56     }
    57 }
    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    数组作为函数参数传递时
    Tree 笨方法实现
    双向链表
    带头节点的循环链表及两个循环链表的合并
    josephus问题->不带头节点的循环链表
    数组形式链表
    检测qq是否在线
    Python-requests模块
    Python面向对象练习——基于面向对象设计一个对战游戏
    Python-面向对象
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/10300884.html
Copyright © 2020-2023  润新知