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 10Output
00210466Note
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 (线段树+分治思路)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐系列文章:《DotText源码阅读》
- 下一篇: Safari browser and a