日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/18 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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,?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';}} }

轉載于:https://www.cnblogs.com/qieqiemin/p/11491557.html

總結

以上是生活随笔為你收集整理的Sereja and Brackets CodeForces - 380C (线段树+分治思路)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。