【题意】给一个括号字符串,然后m个查询,查询【L,R】区间里最大的括号匹配数。
【解题方法】虽然是E题,但我不得不说这是个很水的题。我们只需要考虑一下每个区间没匹配左括号的个数,没匹配的右括号的个数,以及匹配的括号数即可。接下来就是区间合并的典型套路了。
【AC 代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1e6+10;
char s[maxn];
struct node{
int l,r;
int a,b,ans;
}Tree[maxn<<2];
void pushup(int rt){
int tt=min(Tree[rt*2].a,Tree[rt*2+1].b);
Tree[rt].a=Tree[rt*2].a+Tree[rt*2+1].a-tt;
Tree[rt].b=Tree[rt*2].b+Tree[rt*2+1].b-tt;
Tree[rt].ans=Tree[rt*2].ans+Tree[rt*2+1].ans+tt*2;
}
void Build(int l,int r,int rt){
Tree[rt].l=l,Tree[rt].r=r;
if(l==r){
if(s[l-1]=='(') Tree[rt].a++;
else Tree[rt].b++;
Tree[rt].ans=0;
return ;
}
int mid=(l+r)/2;
Build(l,mid,rt*2);
Build(mid+1,r,rt*2+1);
pushup(rt);
}
int ans,now;
node queryans(int L,int R,int rt){
if(L==Tree[rt].l&&Tree[rt].r==R){
return Tree[rt];
}
int mid=(Tree[rt].l+Tree[rt].r)/2;
if(R<=mid) return queryans(L,R,rt*2);
else if(L>mid) return queryans(L,R,rt*2+1);
else{
node as;
node as1=queryans(L,mid,rt*2);
node as2=queryans(mid+1,R,rt*2+1);
int tt=min(as1.a,as2.b);
as.a=as1.a+as2.a-tt;
as.b=as1.b+as2.b-tt;
as.ans=as1.ans+as2.ans+tt*2;
return as;
}
}
int main(){
cin>>s;
int n=strlen(s);
Build(1,n,1);
int q,l,r;
cin>>q;
for(int i=1; i<=q; i++){
cin>>l>>r;
node tmp=queryans(l,r,1);
cout<<tmp.ans<<endl;
}
}