CSPS 2019 Day1 T2 括号树

Description

Link

Solution

树形 dp。

合法括号串本质上有两个

  1. 单独串,如 ()。单独串仅有一队括号构成,如 ()() 有两个单独串。
  2. 嵌套串,如 (()())。嵌套串的定义大于单独串,如 (()()) 为一个嵌套串,且它的子串中没有单独串。

性质 1:单独串和嵌套串可以与其他的合法括号串匹配。

性质 2:如果 有(,那么等待之后的 )。如果 ) 前没有 ) 与它匹配,则没有包括它的合法括号串。

有了上述性质后,状态与转移方程也呼之欲出了。

f i f_i 为从根节点到 i i 的路径上的合法括号子串数。

l s t i lst_i 为在 x x 的上方,第一个等待匹配的 ( 的结点。

c n t i cnt_i i i 到根节点的路径上连续的单独串与嵌套串的个数。如 ()(()())() 依次为 ()(()())()

状态转移见代码。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
char s[N];
ll fa[N], f[N], lst[N], cnt[N], n, ans; 
int main(){
	scanf("%lld%s", &n, s + 1);
	for (int i = 2; i <= n; i++) scanf("%lld", &fa[i]);
	for (int x = 1; x <= n; x++) {
		f[x] = f[fa[x]], lst[x] = lst[fa[x]];
		if (s[x] == '(') lst[x] = x;
		else if (lst[x]) cnt[x] = cnt[fa[lst[x]]] + 1, lst[x] = lst[fa[lst[x]]], f[x] = f[x] + cnt[x];
		ans ^= x * f[x];
	}
	printf("%lld\n", ans);
	return 0;
}
发布了28 篇原创文章 · 获赞 38 · 访问量 501

猜你喜欢

转载自blog.csdn.net/qq_39984146/article/details/104209512