已经没有什么好害怕的了

来源:互联网 发布:平板电脑炒股软件 编辑:程序博客网 时间:2024/04/28 06:38

题意

给定一个长度为n 只包含左括号和右括号的序列,求每一个位置经过的合法子串有多少个。
空串是一个合法的串,如果A 和B 都是合法的串,那么(A) 和AB 都是合法的串。
ans[i]为第i位的答案,对于每组数据,输出一个整数ans=1n(ans[i]i mod P),P=19+7

n106
数据组数T10

Time Limits:1000ms
Memory Limits:512M

分析

我们可以先用栈 处理出每对配对的括号(从左到右,左括号入栈,右括号弹出栈顶与之配对),然后用简单的递推计算即可。

代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int N = 1e6 + 10;const LL P = 1e9 + 7;int n,Inf;int a[N],l[N],r[N];int st[N],next[N],last[N];char in[N];LL ans,t[N];void init() {    scanf(" %s",in + 1);    n = strlen(in + 1);}void pre() {    memset(st,0,sizeof(st));    memset(last,0,sizeof(last));    memset(next,0,sizeof(next));    int top = 0;    for (int i = 1;i <= n;i ++) if (in[i] == '(') st[++ top] = i;    else if (top) next[st[top]] = i + 1,last[i + 1] = st[top --];}void solve() {    memset(l,0,sizeof(l));    memset(r,0,sizeof(r));    memset(t,0,sizeof(t));    for (int i = n + 1; i >= 1;i --) {        r[i]++;        r[last[i]] += r[i];    }    for (int i = 1;i <= n;i ++) {        l[i]--;        l[next[i]] += l[i];    }    for (int i = 1;i <= n;i ++) t[i] = r[i] + l[i];    for (int i = 1;i <= n;i ++) t[i] += t[i-1];    LL ans = 0;    for (int i = 1;i <= n;i ++) ans += 1LL * i * t[i] % P;    printf("%lld\n",ans);}int main() {    int T;    scanf("%d",&T);    while (T --) {        init();        pre();        solve();    }}
0 0
原创粉丝点击