51nod 1791 合法括号子段

来源:互联网 发布:学生信息管理系统mysql 编辑:程序博客网 时间:2024/06/05 02:39

分治

每层,处理左端点在左区间,右端点在右区间的情况下是数量。其总和就是答案。

#include<bits/stdc++.h>using namespace std;const int MAXN=1100100;long long ans;char s[MAXN];int sum_l[MAXN],sum_r[MAXN],cnt[MAXN<<1],mn[MAXN],mx[MAXN];void merge(int l,int r){if(l==r)return;int mid,i;mid=(l+r)>>1;merge(l,mid);merge(mid+1,r);mn[mid]=1<<30;sum_r[mid]=0;for(i=mid+1;i<=r;i++){if(s[i]=='(')sum_r[i]=sum_r[i-1]+1;elsesum_r[i]=sum_r[i-1]-1;mn[i]=min(mn[i-1],sum_r[i]);if(sum_r[i]==mn[i])cnt[-sum_r[i]+MAXN]++;} sum_l[mid+1]=mx[mid+1]=0;for(i=mid;i>=l;i--){if(s[i]=='(')sum_l[i]=sum_l[i+1]+1;elsesum_l[i]=sum_l[i+1]-1;mx[i]=max(mx[i+1],sum_l[i]);if(sum_l[i]==mx[i])ans+=cnt[sum_l[i]+MAXN];}for(i=mid+1;i<=r;i++){if(sum_r[i]<=mn[i])cnt[-sum_r[i]+MAXN]--;}}int main(){int T;memset(cnt,0,sizeof(cnt));scanf("%d",&T);while(T--){scanf("%s",&s);ans=0;merge(0,strlen(s)-1);printf("%lld\n",ans);}}


原创粉丝点击