题解:CF380C Sereja and Brackets
居然让我一遍过了......
Pro
查询区间内最长合法序列。
Sol
定义 表示不可匹配左括号, 同理。
那么考虑如何从 和 推出 。
最容易想到的是 ,但是作为一道不是板子题的题,怎么可能这么简单?
容易发现,我们遗漏了两边括号可以合并的括号对,这里一共有 。
所以 。
然后查询时用同样的套路即可。
Code
#include<bits/stdc++.h>
using namespace std;
int n;
struct Segment_tree{
string s;
int w1[4*1000005],w2[4*1000005];
void pushup(int u)
{
w1[u]=w1[u*2]+w1[u*2+1]-min(w1[u*2],w2[u*2+1]);
w2[u]=w2[u*2]+w2[u*2+1]-min(w1[u*2],w2[u*2+1]);
}
void build(int u=1,int l=1,int r=n)
{
if(l==r)
{
w1[u]=(s[l]=='(');
w2[u]=(s[l]==')');
return;
}
int mid=(l+r)/2;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
bool InRangeOf(int L,int R,int l,int r)
{
return (l<=L)&&(R<=r);
}
bool OutRangeOf(int L,int R,int l,int r)
{
return (L>r)||(R<l);
}
pair<int,int> query(int l,int r,int u=1,int L=1,int R=n)
{
if(InRangeOf(L,R,l,r)) return make_pair(w1[u],w2[u]);
else if(!OutRangeOf(L,R,l,r))
{
int mid=(L+R)/2;
pair<int,int> ls=query(l,r,u*2,L,mid),
rs=query(l,r,u*2+1,mid+1,R);
return make_pair((ls.first+rs.first-min(ls.first,rs.second)),(ls.second+rs.second-min(ls.first,rs.second)));
}
else return make_pair(0,0);
}
}a;
int main()
{
cin>>a.s;
n=a.s.size();
a.s=" "+a.s;
a.build();
int q;
cin>>q;
while(q--)
{
int l,r;
cin>>l>>r;
cout<<(r-l+1-a.query(l,r).first-a.query(l,r).second)<<endl;
}
return 0;
}

浙公网安备 33010602011771号