CSP-S 2019 括号树

\(\text{括号树}\)

本题中合法括号串的定义如下:

\(()\) 是合法括号串。
如果 \(A\) 是合法括号串,则\((A)\) 是合法括号串。
如果 \(A\)\(B\) 是合法括号串,则 \(AB\) 是合法括号串。
\(Q\) 定义 \(s_i\)为:将根结点到\(i\)号结点的简单路径上的括号,按结点经过顺序依次排列组成的字符串。
\(s_i\)共有\(k_i\)个不同子串是合法括号串, 你只需要告诉小 Q 所有 \(i * k_i\)\(xor\)

subtask1 \(\text {期望得分 10pts}\)

\(O(n^2)\)枚举区间 \(O(n^2)\)判断 时间复杂度\(O(n ^ 4)\)

subtask2 \(\text {期望得分 55 pts}\)

链上的部分分 因为是合法括号序列数 可以考虑动态规划
用栈辅助维护第\(i\)个括号可以对应匹配的括号序列数\(cnt[i]\)

\[f[i] = f[pre[i]] + cnt[i] \]

时间复杂度\(O(n)\)

std \(\text {期望得分 100pts}\)

想到链\(55pts\)正解应该也能想出来

\[f[u] = f[fa[tmp]] + cnt[u] \]

inline void dfs (int u) {
	int tmp = 0;
	if (ch[u] == ')') {
		if (top) {
			tmp = s[top];
			f[u] = f[fa[tmp]] + 1;
			top -- ;
		}
	} else if (ch[u] == '(') s[++top] = u;
	sum[u] = sum[fa[u]] + f[u];
	for (int i = head[u]; i; i = edge[i].next) dfs (edge[i].to);
	if (tmp) {
		s[++top] = tmp;
	} else if (top) top -- ;
}

分析

暴力\(55\)貌似不难\(O(n ^ 2)\)就行了
想到链的部分分后正解就不是特别难 评级为 提高/提高+

posted @ 2020-01-19 11:42  Hock  阅读(443)  评论(0编辑  收藏  举报