Noip2019 括号树

1 篇文章 0 订阅
f[i]表示:以i结尾的合法序列的个数。
我们用栈来记录’(‘的位置,对于当前出现的一个’(’,我们将它放入栈中;对于当前出现的一个’)’,如果栈为空,则无贡献,如果栈不为空,则可得:f[i]+=f[fa[sta[top]]]。
因为f[i]表示以i结尾的合法序列的个数,所以最后需要将以i节点的若干个祖先节点为结尾的合法序列的个数,累加至f[i]中,即:f[i]+=f[fa[i]]。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;
int n,top;
int fa[N],sta[N],f[N];
int ans;
char str[N];
int cnt,head[N];
struct edge{int next,to;}e[N];

inline void add(int u,int v)
{
	cnt++;
	e[cnt].next=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}

void dfs(int u)
{
	int jay=0;
	if (str[u]=='(') sta[++top]=u;
	else if (top)
	{
		jay=sta[top];
		f[u]=f[fa[sta[top]]]+1;
		top--;
	}
	for (register int i=head[u]; i; i=e[i].next) dfs(e[i].to);
	if (str[u]=='(') top--;
	else if (jay)
	{
		sta[++top]=jay;
	}
}
void dfs2(int u)
{
	for (register int i=head[u]; i; i=e[i].next)
	{
		f[e[i].to]+=f[u];
		dfs2(e[i].to);
	}
}

signed main(){
	scanf("%lld",&n);
	scanf("%s",str+1);
	for (register int i=2; i<=n; ++i)
	{
		scanf("%lld",&fa[i]);
		add(fa[i],i);
	}
	dfs(1);
	dfs2(1);
	for (register int i=1; i<=n; ++i) ans^=i*f[i];
//	for (register int i=1; i<=n; ++i) printf("%lld ",f[i]); puts("");
	printf("%lld\n",ans);
return 0;	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值