CSP-S 2019 D1T2括号树

Solution

(dfs)一遍。用一个栈储存左括号,遇到一个右括号便能消掉一个左括号,可以这样来给做右括号配对。
注意形如(()())的序列有两个合法子串,((()))却只有一个。(()(()))同样有两个。所以(((())))这样的序列在搜索到最右端时对合法子串个数的贡献与(())相同。注意到若与右括号配对的左括号前面是右括号,搜索到最右端时对合法子串个数的贡献便有可能+1。

#include<bits/stdc++.h>
using namespace std;
const int N=5*1e5+10;
long long hd[N],nxt[N*2],tot,ver[N],n;
long long ans;
char c[N];
void add(int u,int v){
	nxt[++tot] = hd[u];
	ver[tot] = v;
	hd[u] = tot; 
}
long long s[N],top = 0,cont[N],sum[N],fa[N];
void dfs(int x){
	int t = 0;
	if(c[x] == ')' && top != 0){
		t = s[top--];
		cont[x] = cont[fa[t]] + 1;
	}
	else if(c[x] == '('){
		s[++top] = x;
	}
	sum[x] = cont[x] + sum[fa[x]];
	for(int i = hd[x]; i; i = nxt[i])
		dfs(ver[i]);
	if(t == 0)
		if(top != 0) top--;
	if(t != 0)
		s[++top] = t;
}
int main(){
	cin >> n;
	scanf("%s",c+1);
	for(int i = 2; i <= n; i++){
		cin >> fa[i];
		add(fa[i],i);
	}
	dfs(1);
	for(int i = 1; i <= n; i++)
		ans ^= (long long)i * sum[i];  
	cout << ans;
	return 0;
} 
原文地址:https://www.cnblogs.com/FoxC/p/13829335.html