• 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;
    } 
    
  • 相关阅读:
    如何实现EndNote中的PDF批量导出
    UltraEdit 编译输出中文乱码的解决办法
    史密斯(smith)圆图讲解
    OpenFlow
    网络虚拟化-简介
    java util包概述
    内存四区分析
    理解Java接口
    Ubuntu14.04安装wineqq国际版
    使用注解来构造IoC容器
  • 原文地址:https://www.cnblogs.com/FoxC/p/13829335.html
Copyright © 2020-2023  润新知