【五校联考1day1】已经没有什么好害怕的了 题解

【五校联考1day1】已经没有什么好害怕的了 题解

看一个例子()()()(),在结尾加上(

在这里插入图片描述

上面这个图就是表示了红色的数字就是下一个左括号的红色数字加一(右括号的数字为 1 1 1),新加的左括号为 1 1 1;蓝色数字就是上一个左括号的蓝色数字减一(右括号的数字为 − 1 -1 1),第一个左括号为 − 1 -1 1。然后其实就是递推求出这些数字。而红蓝色数组的和就是一个差分数组,表示这一个数与上一个数的差值,所以就前缀和一下边算边计算答案。

怎么证明上述方法是正确的呢?下面设红色数组为 a a a,蓝色为 b b b

a 1 + b 1 = a n s 1 a_1+b_1=ans_1 a1+b1=ans1,这是显然的,也是正确的。然后对于每一个右括号位置 i i i,有 a i + b i = 0 a_i+b_i=0 ai+bi=0,这是因为右括号其实就是与其配对的左括号的值。

考虑剩下的左括号(只对于上面的例子):

下面 i i i为第几个左括号。

对于 i = 1 i=1 i=1,其区间有 [ 1 , 2 ] , [ 1 , 4 ] , [ 1 , 6 ] , [ 1 , 8 ] [1,2],[1,4],[1,6],[1,8] [1,2],[1,4],[1,6],[1,8]

对于 i = 2 i=2 i=2,其区间有 [ 1 , 4 ] , [ 1 , 6 ] , [ 1 , 8 ] , [ 3 , 4 ] , [ 3 , 6 ] , [ 3 , 8 ] [1,4],[1,6],[1,8],[3,4],[3,6],[3,8] [1,4],[1,6],[1,8],[3,4],[3,6],[3,8]

对于 i = 3 i=3 i=3,其区间有 [ 1 , 6 ] , [ 1 , 8 ] , [ 3 , 6 ] , [ 3 , 8 ] , [ 5 , 6 ] , [ 5 , 8 ] [1,6],[1,8],[3,6],[3,8],[5,6],[5,8] [1,6],[1,8],[3,6],[3,8],[5,6],[5,8]

对于 i = 4 i=4 i=4,其区间有 [ 1 , 8 ] , [ 3 , 8 ] , [ 5 , 8 ] , [ 7 , 8 ] [1,8],[3,8],[5,8],[7,8] [1,8],[3,8],[5,8],[7,8]

其实有个显然的事情,对于 i i i,有一些区间一定有一些来自 i − 1 i-1 i1的区间,而有一些则被删掉了, ∣ b i ∣ − 1 |b_i|-1 bi1为删掉的数量,所以之所以有 b i = b j − 1 ( j < i ) b_i=b_j-1(j<i) bi=bj1(j<i) j j j是上一个左括号的位置),原因就是删掉的数量是每一次比上次多了 1 1 1。对于 a a a同理。

大家可以手磨一些数据,可以发现更好的规律。

#include<bits/stdc++.h>
using namespace std;
int t,n,b[1000005],c[1000005],d[1000005],e[1000005],s[1000005];
char a[1000005];
typedef long long ll;
const int mod=1e9+7;
int main(){
	scanf("%d",&t);
	while (t--){
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		memset(d,0,sizeof(d));
		memset(e,0,sizeof(e));
		scanf("%s",a+1);
		n=strlen(a+1);
		int top=0;
		for (int i=1;i<=n;i++){
			if (a[i]=='(') s[++top]=i;
			else{
				if (top>0){
					b[i+1]=s[top];
					c[s[top]]=i+1;
					top--;
				}
			}
		}
		for (int i=n+1;i>=1;i--) d[i]=1;
		for (int i=n+1;i>=1;i--) d[b[i]]+=d[i];
		for (int i=1;i<=n;i++) e[i]=-1;
		for (int i=1;i<=n;i++) e[c[i]]+=e[i];
		ll sum=0;
		ll ans=0;
		for (int i=1;i<=n;i++){
			sum+=(ll)e[i]+(ll)d[i];
			ans+=(ll)((1ll*sum*i)%mod);
		}
		printf("%lld\n",ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值