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 l**i, r**i(1 ≤ l**i ≤ r**i ≤ 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, ..., 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 l**i, r**i (1 ≤ l**i ≤ r**i ≤ 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 = s**k1s**k2... 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,代表一个区间。对于每一个询问,让你输出区间中能选出最长的子序列是合法的括号序列的长度。

思路:

对询问区间进行离线保存,以右端点升序来排序,

然后从坐向右扫描,用stack来维护每一个还没被匹配到的(字符的下标,

当来一个)字符的时候,将其和栈顶的那个(匹配,同时用树状数组在(的下标的数值上+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,x,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), 0, 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 id;
} a[maxn];
char s[maxn];
int n;
int m;
bool cmp(node aa, node bb)
{
    return aa.r < bb.r;
}
int tree[maxn];
int lowbit(int x)
{
    return x & (-1 * x);
}
void add(int x, int val)
{
    while (x <= n) {
        tree[x] += val;
        x += lowbit(x);
    }
}
int ask(int x)
{
    int res = 0;
    while (x) {
        res += tree[x];
        x -= lowbit(x);
    }
    return res;
}
int ans[maxn];
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    gbtb;
    cin >> s + 1;
    n=strlen(s+1);
    cin >> m;
    repd(i, 1, m ) {
        cin >> a[i].l >> a[i].r;
        a[i].id = i;
    }
    sort(a + 1, a + 1 + m, cmp);
    stack<int> st;
    while (sz(st)) {
        st.pop();
    }
    int pos = 1;
    repd(i, 1, m) {
//        chu(pos);
        repd(j, pos, a[i].r) {
            if (s[j] == '(') {
                st.push(j);
            } else {
                if (sz(st)) {
                    add(st.top(), 2);
                    st.pop();
                }
            }
        }
        ans[a[i].id] = ask(a[i].r) - ask(a[i].l - 1);
        pos = a[i].r + 1;
    }
    repd(i,1,m)
    {
        printf("%d\n",ans[i] );
    }

    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';
        }
    }
}




posted @ 2019-09-09 15:32  茄子Min  阅读(155)  评论(0编辑  收藏  举报