zoukankan      html  css  js  c++  java
  • P5658 括号树

    P5658 括号树

    NOIp2019

    我是永远不会忘记我那天在考场上傻瞪着题啥都不会的心理阴影的……

    于是今天我克服心理阴影来写这道题。

    树形结构

    因为这是一个树,所有优秀的性质这个题都有。并且题目仅仅是问从1开始到所有点的答案,所以我们就可以依靠树的性质来做。

    首先,对于一个节点,我们给它记录几个值:

    • (lst_i)表示i的贡献(只是i的贡献,并不包括从根节点到i路径上点的贡献)
      • 那么我们发现这个lst是如何转移的。考虑一条到i的路径,如果i是后括号,那么(lst_i)即为与之配对的前括号的父节点的(lst)+1。因为假设这个前括号的父节点同样有一个已经匹配了的后括号,那么我们势必可以把当前的匹配和之前的匹配序列合并,当前的这个后括号的贡献值,其实就等于前面那个后括号的贡献值+1
    • (sum_i)表示从根节点到i的贡献的和。那么转移就是(sum_i=sum_{fa_i}+lst_i)

    最后答案即为每个sum乘i的异或和。

    然后按照树dfs一遍即可……吗?

    dfs

    对于前括号和后括号我们用一个栈维护即可。遇到前括号入栈,后括号出栈并用上述方式处理,如果空栈就跳过。这里只需要注意一点:dfs之后需要将栈内修改的值重新放回去。

    其余就没什么了。

    (做不出来还是我太蔡了)

    记得开long long。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<stack>
    #define int long long
    using namespace std;
    inline int read(){
    	int x=0,w=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return w?-x:x;
    } 
    namespace star
    {
    	const int maxn=5e5+10;
    	int n,fa[maxn],ans,lst[maxn];
    	char s[maxn];
    	int ecnt,head[maxn],nxt[maxn],to[maxn],sum[maxn];
    	inline void addedge(int a,int b){
    		to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt;
    	}
    	stack<int> st;
    	void dfs(int x){
    		int tmp=0;
    		if(s[x]=='(')st.push(x);
    		else{
    			if(!st.empty()){
    				tmp=st.top();
    				st.pop();
    				lst[x]=lst[fa[tmp]]+1;
    			}
    		}
    		sum[x]=sum[fa[x]]+lst[x];
    		for(int i=head[x];i;i=nxt[i])dfs(to[i]);
    		if(tmp)st.push(tmp);
    		else if(!st.empty())st.pop();
    	}
    	inline void work(){
    		n=read();
    		scanf("%s",s+1);
    		for(int a,i=2;i<=n;i++)
    			a=read(),addedge(a,i),fa[i]=a;
    		dfs(1);
    		for(int i=1;i<=n;i++)
    			ans^=(sum[i]*i);
    		printf("%lld",ans);
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    作业5

    Linux系统管理4
    作业
    递归训练1:在两个长度相等的排序数组中找到上中位数
    LeetCode:面试题 08.05. 递归乘法
    LeetCode:面试题 08.06. 汉诺塔问题
    LeetCode:22. 括号生成
    如何仅用递归函数和栈操作逆序一个栈
    LeetCode:面试题 03.02. 栈的最小值
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13544799.html
Copyright © 2011-2022 走看看