tr数组存四个值,L,R,left,right;
left代表[L,R]区间内不合法的左括号数,right代表[L,R]区间内不合法的右括号数。
叶节点如果是'(',则left=1,right=1; 叶节点如果是')',则left=0,right=1;
void pushup(int u){
tr[u].left=tr[u<<1].left+tr[u<<1|1].left-min(tr[u<<1].left,tr[u<<1|1].right);
tr[u].right=tr[u<<1].right+tr[u<<1|1].right-min(tr[u<<1].left,tr[u<<1|1].right);
}
子节点到父节点恢复合法括号数num=min(左子节点不合法左括号数,右子节点不合法右括号数)
父节点的不合法的左括号数=左子节点的不合法的左括号数+右子节点的不合法的左括号数
父节点的不合法的右括号数=左子节点的不合法的右括号数+右子节点的不合法的右括号数
tips:可以使用merge来处理返回node形式的query函数
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct node{
int l,r,left,right;
};
node tr[N<<2];
char s[N];
void pushup(int u){
tr[u].left=tr[u<<1].left+tr[u<<1|1].left-min(tr[u<<1].left,tr[u<<1|1].right);
tr[u].right=tr[u<<1].right+tr[u<<1|1].right-min(tr[u<<1].left,tr[u<<1|1].right);
}
node merge(node x,node y){
node op={0,0,0,0};
op.left=x.left+y.left-min(x.left,y.right);
op.right=x.right+y.right-min(x.left,y.right);
return op;
}
void build(int u,int l,int r){
if(l==r){
if(s[l]=='(') tr[u]={l,r,1,0};
else tr[u]={l,r,0,1};
}
else{
tr[u]={l,r,0,0};
int mid=(tr[u].l+tr[u].r)>>1;
build(u<<1,l,mid); build(u<<1|1,mid+1,r);
pushup(u);
}
}
node query(int u,int l,int r){
if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
else{
node res={0,0,0,0};
int mid=(tr[u].l+tr[u].r)>>1;
if(l<=mid) res=query(u<<1,l,r);
if(r>mid) res=merge(res,query(u<<1|1,l,r));
return res;
}
}
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
build(1,1,n);
int q;
scanf("%d",&q);
while(q--){
int l,r;
scanf("%d %d",&l,&r);
node res=query(1,l,r);
printf("%d\n",(r-l+1)-res.left-res.right);
}
return 0 - 0;
}