1 条题解
-
0
我们将使用线段树来维护。在每个节点处存储以下信息:
- —— 该区间内最长正确括号子序列的长度
- —— 该区间内未被匹配的开括号
'('的数量 - —— 该区间内未被匹配的闭括号
')'的数量
如果我们想要合并两个节点,其参数分别为 和 ,可以使用以下规则:
注意:原公式中 仅计算了“匹配的对数”,最终实际长度应为 。原代码实现中通常以“对数”存储,或者最后乘以 ,请根据实现调整。
#include<bits/stdc++.h> using namespace std; struct A{ int a; int b; int c; }; vector<A> v; string s; A combine(A l,A r){ int t=min(l.b,r.c); return {l.a+r.a+t,l.b+r.b-t,l.c+r.c-t}; } void build(int t,int l ,int r){ if(l==r){ if(s[l]=='('){ v[t]={0,1,0}; } else{ v[t]=A{0,0,1}; } return; } int mid =(l+r)/2; build(2*t,l,mid); build(2*t+1,mid+1,r); v[t]=combine(v[2*t],v[2*t+1]); } A query(int t,int tl,int tr,int l,int r){ if(l>r){return{0,0,0};} if(tl==l&&tr==r){return v[t];} int tmid=(tl+tr)/2; A a=query(t*2,tl,tmid,l,min(r,tmid)); A b=query(t*2+1,tmid+1,tr,max(l,tmid+1),r); return combine(a,b); } int main(){ cin>>s; v.resize(4*s.length()); build(1,0,s.length()-1); int m; cin>>m; int l,r; while(m--){ cin>>l>>r; cout<<query(1,0,s.length()-1,l-1,r-1).a*2<<"\n"; } }
- 1
信息
- ID
- 6765
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者