• Codeforces Round #223 (Div. 2) E. Sereja and Brackets 线段树区间合并


    E. Sereja and Brackets
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Sereja has a bracket sequence s1, s2, ..., sn, or, in other words, a string s of length n, consisting of characters "(" and ")".

    Sereja needs to answer m queries, each of them is described by two integers li, ri (1 ≤ li ≤ ri ≤ n). The answer to the i-th query is the length of the maximum correct bracket subsequence of sequence sli, sli + 1, ..., sri. Help Sereja answer all queries.

    You can find the definitions for a subsequence and a correct bracket sequence in the notes.

    Input

    The first line contains a sequence of characters s1, s2, ..., sn (1 ≤ n ≤ 106) without any spaces. Each character is either a "(" or a ")". The second line contains integer m (1 ≤ m ≤ 105) — the number of queries. Each of the next m lines contains a pair of integers. The i-th line contains integers li, ri (1 ≤ li ≤ ri ≤ n) — the description of the i-th query.

    Output

    Print the answer to each question on a single line. Print the answers in the order they go in the input.

    Examples
    input
    ())(())(())(
    7
    1 1
    2 3
    1 2
    1 12
    8 12
    5 11
    2 10
    output
    0
    0
    2
    10
    4
    6
    6
    Note

    subsequence of length |x| of string s = s1s2... s|s| (where |s| is the length of string s) is string x = sk1sk2... sk|x|(1 ≤ k1 < k2 < ... < k|x| ≤ |s|).

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

    For the third query required sequence will be «()».

    For the fourth query required sequence will be «()(())(())».

    题意:给你一个括号序列,q个询问,求区间内括号匹配的数量;

    思路:线段数区间合并;

       一个线段树存三个数,l,m,r;

       l表示区间内除去以匹配的左括号的数量;

       r表示区间内除去以匹配的右括号的数量;

       m表示匹配好的左右括号的数量;

       对于左边的区间,和右边的区间,只要将 左边的l和右边的尽量匹配即可;

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-14
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e6+2,M=1e7+10,inf=1e9+10;
    const ll INF=1e18+10,mod=1e9+7;
    
    ///   数组大小
    char s[N];
    
    struct ans
    {
        int x,y,z;
        ans(){}
        ans(int xx,int yy,int zz)
        {
            x=xx;y=yy;z=zz;
        }
    };
    
    struct SGT
    {
        int LT[N<<2],RT[N<<2],MT[N<<2];
        void pushup(int pos)
        {
            int k=min(LT[pos<<1],RT[pos<<1|1]);
            MT[pos]=MT[pos<<1]+MT[pos<<1|1]+2*k;
            LT[pos]=LT[pos<<1]+LT[pos<<1|1]-k;
            RT[pos]=RT[pos<<1]+RT[pos<<1|1]-k;
        }
        void build(int l,int r,int pos)
        {
            if(l==r)
            {
                LT[pos]=0;
                RT[pos]=0;
                MT[pos]=0;
                if(s[l]=='(')
                    LT[pos]++;
                else
                    RT[pos]++;
                return;
            }
            int mid=(l+r)>>1;
            build(l,mid,pos<<1);
            build(mid+1,r,pos<<1|1);
            pushup(pos);
        }
        ans query(int L,int R,int l,int r,int pos)
        {
            if(L==l&&r==R)
                return ans(LT[pos],MT[pos],RT[pos]);
            int mid=(l+r)>>1;
            if(R<=mid)
                return query(L,R,l,mid,pos<<1);
            else if(L>mid)
                return query(L,R,mid+1,r,pos<<1|1);
            else
            {
                ans a=query(L,mid,l,mid,pos<<1);
                ans b=query(mid+1,R,mid+1,r,pos<<1|1);
                int k=min(a.x,b.z);
                int m=a.y+b.y+2*k;
                int l=a.x+b.x-k;
                int r=a.z+b.z-k;
                return ans(l,m,r);
            }
        }
    };
    SGT tree;
    int main()
    {
        scanf("%s",s+1);
        int x=strlen(s+1);
        tree.build(1,x,1);
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d
    ",tree.query(l,r,1,x,1).y);
        }
        return 0;
    }
    /*
    ))(()))))())())))))())((()()))))()))))))))))))
    9
    26 42
    21 22
    6 22
    7 26
    43 46
    25 27
    32 39
    22 40
    2 45
    */
  • 相关阅读:
    VS2010 VC Project的default Include设置
    Linux 下的编辑/编译器
    用命令实现Win7远程桌面关机和重启
    怎样快速刪除Word中超链接?
    chrome浏览器世界之窗浏览器的收藏夹在哪?
    代码量查找工具[最好用的]
    C项目实践--网络协议和套接字编程
    memmove 和 memcopy
    bzoj2456: mode
    bzoj1205: [HNOI2005]星际贸易
  • 原文地址:https://www.cnblogs.com/jhz033/p/6675229.html
Copyright © 2020-2023  润新知