CodeForces Round 213 Div 2 E Sereja and Brackets 线段树

来源:互联网 发布:179端口 编辑:程序博客网 时间:2024/05/08 14:36

我本来觉得这个题不能用线段树的,因为联想到从前做的有关括号的匹配的问题好像都是DP的,如果直接线段树的话就有点贪心的意思。但是仔细想想,这题只是匹配,用线段树非常合适,因为括号分成两部分,左边和右边,线段树也都是二分的,所以统计每一层节点的 左括号, 完整括号 和右括号,上一层的节点的 完整括号就等于 用左儿子的左括号匹配右儿子的右括号 再加上完整的括号就可以了。非常易用的可加性。还是个没有更新的线段树,非常简单那。

我输入的字符串时候是从0开始的,线段树 build 的时候是从 1 开始的, 小卡一下。

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1#define MAX 1000003struct node{int l;int r;int b;node(){l = r = b = 0;}node(int aa,int bb,int cc){l = aa;r = bb;b = cc;}};node dat[MAX<<2];char bra[MAX];void PushUp(int rt){int t = min(dat[rt<<1].l,dat[rt<<1|1].r);dat[rt].b = dat[rt<<1].b + dat[rt<<1|1].b + t;dat[rt].l = dat[rt<<1].l + dat[rt<<1|1].l - t;dat[rt].r = dat[rt<<1].r + dat[rt<<1|1].r - t;}void build(int l, int r, int rt){if(r == l){if(bra[l-1] == '('){dat[rt].l = 1;dat[rt].r = 0;dat[rt].b = 0;}else if(bra[l-1] == ')'){dat[rt].l = 0;dat[rt].r = 1;dat[rt].b = 0;}return ;}int m = (l + r) >> 1;build(lson);build(rson);PushUp(rt);}node dumy;node query(int a, int b, int l, int r, int rt){if(a > r || b < l)return dumy;if(a <= l && r <= b)return dat[rt];int m = (l + r) >> 1;node t1 = query(a,b,lson);node t2 = query(a,b,rson);int t = min(t1.l,t2.r);return node(t1.l + t2.l - t, t1.r + t2.r - t, t1.b + t2.b + t);}int main(){dumy.l = dumy.r = dumy.b = 0;scanf("%s",bra);int len = strlen(bra);build(1,len,1);int n;cin >> n;for(int i = 0; i < n; i ++){int a ,b;cin >> a >> b;cout << query(a,b,1,len,1).b * 2 << endl;;}return 0;}


0 0