CSP-S D1T2

首先看到这个题
先看数据分布
在这里插入图片描述
可以发现,存在55分的链的处理

简易推理可知存在两种情况

  1. 合法括号字串+合法合法括号字串,如 ( )( )( )( )
  2. 合法括号字串里有合法括号字串,如 ( ( ) )
  3. ( + 一大堆无关的玩意 + )

显然可以考虑用栈来解决这个问题
步骤为:
令SUMp为 以p节点为结尾的在根节点到p节点的路径上的单次匹配

  1. 当入栈的为(时,直接把下标存入栈中
    2.当入栈的为)时,必须与栈中(的位置匹配,又因为可以继承(之前的答案,所以操作就很明显了
    SUMp=SUM.(Q.TOP()-1)+1;
    Q.POP();
    然后就ok了
    综上,期望得分55,时间复杂度O(n)

做到这里,后面45分就非常好拿了
考虑将从根节点出发的到每一个节点变化为一条链,然后在这条链上计算答案
又因为答案具有重复计算的特征,故可以考虑一种以O(n)时间复杂度为基础的算法 -----大法师(dfs)

然后关于如何维护每一条链上的栈
再每一次dfs时进行一次回溯就可以解决这个问题


综上,期望得分100,时间复杂度O(n)

#include<bits/stdc++.h>
using namespace std;

long long n,sy,sum[500005],ans=0,h[500005],tot=0,fa[500005];
char kh[500005];
stack<long long>q;

struct node{
	int next,to,from;
}e[500005];

void add(int x,int y){
	tot++;
	e[tot].next=h[x];
	e[tot].to=y;
	e[tot].from=x;
	h[x]=tot;
}

int dfs(int now){
		if(kh[now]=='('){
			q.push(now);
			for(int i=h[now];i;i=e[i].next)dfs(e[i].to);
			q.pop();
		}
		else if(!q.empty()){
			//sum[now]=1+sum[q.top()-1];
			sum[now]=1+sum[fa[q.top()]];
			long long zhongzan=q.top();
			q.pop();
			for(int i=h[now];i;i=e[i].next)dfs(e[i].to);
			q.push(zhongzan);
		}
		else{
			for(int i=h[now];i;i=e[i].next)dfs(e[i].to);
		}
}

int as(int now){
	for(int i=h[now];i;i=e[i].next){
		sum[e[i].to]+=sum[now];
		as(e[i].to);
	}
	ans=ans^(now*sum[now]);
}

int main(){
	//freopen("testdata (1).in","r",stdin);
	cin>>n;memset(sum,0,sizeof(sum));
	for(long long i=1;i<=n;i++)cin>>kh[i];
	for(long long i=1;i<n;i++){
		cin>>sy;
		add(sy,i+1);
		fa[i+1]=sy;
	}
	dfs(1);
	as(1);
	cout<<ans<<endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值