分治
每层,处理左端点在左区间,右端点在右区间的情况下是数量。其总和就是答案。
#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;
else
sum_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;
else
sum_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);
}
}