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,?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 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,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 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 l, 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, l, r); } else if (l > mid) { return ask(rt << 1 | 1, l, r); } else { node res1 = ask(rt << 1, l, r); node res2 = ask(rt << 1 | 1, l, 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, l, 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'; } } }