微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Sereja and Brackets CodeForces - 380C 线段树+分治思路

Sereja and Brackets

题目链接CodeForces - 380C

Sereja has a bracket sequence s1,?s2,?...,?*s**n,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,?*s**n* (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

())(())(())(71 12 31 21 128 125 112 10

Output

00210466

Note

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

A 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和r,代表一个区间。对于每一个询问,让你输出区间中能选出最长的子序列是合法的括号序列的长度。

思路:

线段树+分治的思想来解决此问题。

我们线段树每一个区间维护以下信息:

1、区间中能选出最长的子序列是合法的括号序列的个数 num。

2、 区间中多余的‘(‘ 字符的个数 a

3、区间中多余的‘)‘ 字符的个数 b

那么对于区间合并时,

num=左儿子的num+右儿子的num+min(左儿子的a,右儿子的b)

a=左儿子的a+右儿子的a - min(左儿子的a,右儿子的b)

b=左儿子的b+右儿子的b - min(左儿子的a,右儿子的b)

最后输出时,注意num个括号个数,*2才是长度。

细节见代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(),(x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(),a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X),sizeof((X)))
#define MSC0(X) memset((X),'\0',sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) {return b ? gcd(b,a % b) : a;}
ll lcm(ll a,ll b) {return a / gcd(a,b) * b;}
ll powmod(ll a,ll b,ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
    int l,r;
    int num;
    int a;// (
    int b;// )
} segmeng_tree[maxn << 2];
char s[maxn];
int n;
int m;
void pushup(int rt)
{
    int x = min(segmeng_tree[rt << 1].a,segmeng_tree[rt << 1 | 1].b);
    segmeng_tree[rt].num = x + segmeng_tree[rt << 1].num + segmeng_tree[rt << 1 | 1].num;
    segmeng_tree[rt].a = segmeng_tree[rt << 1].a + segmeng_tree[rt << 1 | 1].a - x;
    segmeng_tree[rt].b = segmeng_tree[rt << 1].b + segmeng_tree[rt << 1 | 1].b - x;
}
void build(int rt,int l,int r)
{
    segmeng_tree[rt].l = l;
    segmeng_tree[rt].r = r;
    if (l == r) {
        segmeng_tree[rt].a = s[l] == '(';
        segmeng_tree[rt].b = s[l] == ')';
        segmeng_tree[rt].num = 0;
    } else {
        int mid = (l + r) >> 1;
        build(rt << 1,l,mid);
        build(rt << 1 | 1,mid + 1,r);
        pushup(rt);
    }
}

node ask(int rt,int r)
{
    if (segmeng_tree[rt].l >= l && segmeng_tree[rt].r <= r) {
        return segmeng_tree[rt];
    }
    int mid = (segmeng_tree[rt].l + segmeng_tree[rt].r) >> 1;
    if (r <= mid) {
        return ask(rt << 1,r);
    } else if (l > mid) {
        return ask(rt << 1 | 1,r);
    } else {
        node res1 = ask(rt << 1,r);
        node res2 = ask(rt << 1 | 1,r);
        node res = res1;
        int x = min(res1.a,res2.b);
        res.num += x;
        res.b += res2.b;
        res.a += res2.a;
        res.num += res2.num;
        res.b -= x;
        res.a -= x;
        return res;
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    scanf("%s",s + 1);
    n = strlen(s + 1);
    build(1,1,n);
    scanf("%d",&m);
    while (m--) {
        int l,r;
        scanf("%d %d",&l,&r);
        printf("%d\n",ask(1,r).num * 2);
    }
    return 0;
}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐