Jzoj4209 已经没有什么好害怕的了

小Y 最近开始学习算法姿势,但是因为小R 非常BB,给了她很多B6 题,所以她觉得自己已经没有什么前途了。

于是小R 给了她一些稍微简单的题,让她觉得已经没有什么好害怕的了,其中一道是这样的:

给定一个长度为n 只包含左括号和右括号的序列,现在小R 想要知道经过每一个位置的合法子串有多少个。

空串是一个合法的串,如果A 和B 都是合法的串,那么(A) 和AB 都是合法的串。 n<=1000000


又是差分的题目,非常坑

先给括号配对,让后记一对合法的括号为[l,r)

我们分别按顺序和倒序处理每对括号[l,r)

对于括号[l,r)我们先对区间[l,r)加上1,让后考虑它的影响

若l是另一对括号[l',r')的右端点(r'=l)那么显然这里的[l,r)贡献可以全部加过去

若r是另一对括号[l',r')的左端点,那么显然也可以把[l,r)的贡献全加过去

不合法的括号位置会自动抵消

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1000010
#define M 1000000007
using namespace std;
long long ans,f[N]; char s[N];
int n,m,t,w[N],l[N],r[N],cl[N],cr[N];
int _18520(){
	scanf("%s",s+1); n=strlen(s+1);
	for(int i=1;i<=n;++i)
		if(s[i]=='(') w[++t]=i;
		else if(t){ r[w[t]]=i+1; l[i+1]=w[t--]; }
	for(int i=n+1;i;--i) cr[l[i]]+=++cr[i];
	for(int i=1;i<=n;++i) cl[r[i]]+=--cl[i];
	for(int i=1;i<=n;++i) f[i]=f[i-1]+cl[i]+cr[i];
	for(int i=1;i<=n;++i) ans=ans+i*f[i]%M;
	printf("%lld\n",ans);
}
int main(){
	int T; 
	for(scanf("%d",&T);T--;_18520()){
		memset(f,0,N<<3);
		memset(l,0,N<<2);
		memset(r,0,N<<2);
		memset(cl,0,N<<2);
		memset(cr,0,N<<2);
		t=ans=0;
	}
}

转载于:https://www.cnblogs.com/Extended-Ash/p/8312578.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值