列表

详情


NC253749. 小红的括号串权值

描述

我们认为一个由')'和'('组成的字符串为匹配的,当且仅当可以通过添加'1'和'+'使得其变成一个合法的运算式。例如,"()()"是匹配的,因为可以变成"(1+1)+(1+1)",而")("则不匹配。
小红定义一个匹配的括号字符串的权值为:
每次操作选择一对相邻的括号对(只能是"()",但不能是")("),将其删除,该操作的代价为这个括号对右边的')'字符数量。
持续这个操作,将该字符串变成空串的最小代价之和,即为原字符串的权值。
例如"()()"是权值为0(先删除右边的那对括号,再删除左边的),而"(())"的权值为1。
对于非匹配的字符串,权值为0。

现在给定一个括号串,请你求出所有连续子串的权值之和。答案对10^9+7取模。

输入描述

一个由')'和'('组成的字符串,长度不超过300000

输出描述

所有子串的权值之和。答案对10^9+7取模。

示例1

输入:

)(())())

输出:

2

说明:

只有两个连续子串的权值是1:"(())"和"(())()",其余子串的权值均为0。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 33ms, 内存消耗: 26492K, 提交时间: 2023-07-07 21:14:15

#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
const int N = 3e5 + 10, P = 1e9 + 7;

string s;

vector<int> g[N];

int n, sz[N];
i64 ans[N], tot;



void dfs(int u) {
    sz[u] = 1;
    for(int v : g[u]) {
        dfs(v);
        sz[u] += sz[v];
        ans[u] += sz[v] + ans[v];
        ans[u] %= P;
    }
    
    for(int i = 0; i < g[u].size(); i ++) {
        int v = g[u][i];
        tot += ans[v] * (i + 1ll) * (g[u].size() - i) % P;
        tot %= P;
    }
}

void solve() {
    cin >> s;
    vector<int> stk(1, 0);
    for(char c : s) {
        if(c == '(') {
            g[stk.back()].push_back(++ n);
            stk.push_back(n);
        }else {
            stk.pop_back();
            if(stk.empty())
                stk.push_back(++ n);
        }
    }
    for(int i = 1; i < stk.size(); i ++) {
        g[stk[i - 1]].pop_back();
    }
    for(int u = 0; u <= n; u ++) {
        if(!sz[u]) dfs(u);
    }
    cout << tot;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    solve();
}

C++(clang++ 11.0.1) 解法, 执行用时: 13ms, 内存消耗: 3304K, 提交时间: 2023-07-08 14:50:14

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
char s[N];
int q[N],pos[N];
int tot;
int main(){
	scanf("%s",s+1);
	int n=strlen(s+1);
	long long ans=0;
	for (int i=1;i<=n;i++) if (s[i]=='('){
		pos[++tot]=i;
		q[tot]=-1;
	}else{
		vector<int>w;
		int s=0;
		while (tot&&q[tot]!=-1){
			w.push_back(q[tot]);
			s=(s+q[tot])%mod;
			tot--;
		}
		for (int j=0;j<w.size();j++) ans=(ans+1ll*(j+1)*((int)w.size()-j)%mod*w[j]%mod)%mod;
		if (tot){
			q[tot]=(s+(i-pos[tot])/2)%mod;
		}
	}
	for (int i=1;i<=tot;i++) 
		if (q[i]>=0){
			int j=i; 
			vector<int>w;
			w.push_back(q[i]);
			while (j<tot&&q[j+1]>=0){
				j++;
				w.push_back(q[j]);
			}
			i=j;
			for (int j=0;j<w.size();j++) ans=(ans+1ll*(j+1)*((int)w.size()-j)%mod*w[j]%mod)%mod;
		}
	printf("%d\n",ans);
}

上一题