题解:CF2201C Rigged Bracket Sequence

· · 题解

CF2201C

考虑将括号序列转化到序列 a 上,令左括号对应的值满足 a_i=1,右括号满足 a_i=-1s_i=s_{i-1}+a_i,则序列合法的充要条件是:\forall i,s_i\geq 0s_n=0

右移 [i_1,i_2,\cdots,i_k] 带来的影响在于:对于 i_m\leq j<i_{m+1}s_j\leftarrow s_j+a_{i_k}-a_{i_m}

分类讨论:

考虑对第二种情况使用动态规划计数。f_i 表示钦定最后一位满足 a_{i_k}=-1 的合法方案数。

如果 f_j 可以转移到 f_i,分类讨论:

$a_j=-1$:全部点可以转移。 最后答案累加即可,对于 $a_i=1$ 的点计入 $2^{i-1}$,否则计入我们动态规划得出的 $f_i$。 #### Code ```cpp #include <bits/stdc++.h> using namespace std; const int md = 998244353; int dc = 1,n,p[300005],a[300005],s[300005],f[300005],g[300005],l[300005],r[300005]; namespace DoubleQLzn { void init() { return ; } void solve() { int lst = 0; cin >> n; p[0] = 1; for (int i = 1;i <= n;i++) { char c; cin >> c; if (c == '(') a[i] = 1; else a[i] = -1; s[i] = s[i - 1] + a[i]; } for (int i = 1;i <= n;i++) p[i] = p[i - 1] * 2 % md; for (int i = 1;i <= n;i++) { int c; if (i != lst) c = (l[i - 1] - l[lst] + md) % md; else c = 0; f[i] = (c + r[i - 1] + 1) % md; if (a[i] == 1) l[i] = (l[i - 1] + f[i]) % md; else l[i] = l[i - 1]; if (a[i] == -1) r[i] = (r[i - 1] + f[i]) % md; else r[i] = r[i - 1]; // cout << c << ' ' << r[i - 1] << ' ' << f[i] << '\n'; if (s[i] <= 1) lst = i; } int ans = 0; for (int i = 1;i <= n;i++) ans = (ans + (a[i] == 1 ? p[i - 1] : f[i])) % md; cout << ans << '\n'; } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T; if (dc == 0) T = 1; else cin >> T; while (T--) { DoubleQLzn::init(); DoubleQLzn::solve(); } return 0; } ```