CF380C Sereja and Brackets
题意:
给一个只有左右括号的序列和n段区间,求每个序列区间中最长的匹配括号子序列的长度。
思路:
线段树,记录每个区间中未匹配的左括号的未匹配的右括号的个数,寻找区间是都是从左往右找,最后答案就是区间长度-1-未匹配的左右括号个数
code:
#include<cstdio> #define N 1000000 using namespace std; struct arr{ int l,r,a,b; }tr[N*4]; int ri,le,n,l; char s[N]; void build(int w,int l,int r){ tr[w].l=l,tr[w].r=r; if (l==r){ if (s[l-1]=='(') tr[w].a++; else tr[w].b++; return; } int mid=(l+r)/2; build(w*2,l,mid); build(w*2+1,mid+1,r); tr[w].a=tr[w*2+1].a; tr[w].b=tr[w*2].b; if (tr[w*2].a>tr[w*2+1].b) tr[w].a+=(tr[w*2].a-tr[w*2+1].b); else tr[w].b+=(tr[w*2+1].b-tr[w*2].a); } void find(int w,int l,int r){ if (tr[w].l==l&&tr[w].r==r){ if (tr[w].b<=le) le-=tr[w].b; else ri+=tr[w].b-le,le=0; le+=tr[w].a; return; } int mid=(tr[w].l+tr[w].r)/2; if (r<=mid) find(w*2,l,r); else if (l>mid) find(w*2+1,l,r); else{ find(w*2,l,mid); find(w*2+1,mid+1,r); } } int main(){ scanf("%s",&s); for (l=0;s[l]!='