P5658 括号树

P5658 括号树

题解

太菜了啥都不会写只能水5分数据

啥都不会写只能翻题解  题解大大我错了

我们手动找一下规律

我们设 w[ i ] 为从根节点到结点 i 对答案的贡献,也就是走到结点 i ,合法括号串又多了几个

sum[ i ] 为从根节点到结点 i 总共合法括号串数

()()()

w[i] 依次为 0  1  0  2  0  3

sum[i] 依次为 0  1  1  3  3  6

())()

w[i] 依次为 0  1  0  0  1

sum[i] 依次为 0  1  1  1  2

()(())

w[i] 依次为 0  1  0  0  1  2

sum[i] 依次为 0  1  1  1  2  4

然后我们惊奇的发现 sum[i] 是 w[i] 的前缀和

最后要求的其实就是所有的 sum[i]*i 的异或和,所以当务之急只找到求解 w[ i ] 的方法

(1)发现如果 s[i] 是个左括号,那么显然不会有新的贡献出现,也就是w[i]=0

(2)如果 s[i] 是个右括号,那么我们找到他对应上一个右括号,贡献值也就是上一个右括号的贡献值+1:其实也就相当于,对于当前右括号,(如果条件允许)他有左括号与之匹配,对答案贡献为1,然鹅当前右括号对应的前一个右括号,他本就会对答案有一定的贡献,加上当前新匹配的一对括号,就生成新的匹配括号串,那么我们就将它作为当前右括号的贡献存下

举个栗子:()()() )()

w[4]=2

s[5]是左括号,那么w[5]=0,因为考虑了s[5]也没有出现新的匹配括号

s[6]是一个可以匹配的右括号,那么,s[5]与s[6]构成一个新的匹配括号,s[3]~s[6]以及s[1]~s[6]都是新匹配的括号,他们都是原来w[4]的基础上又加了新的s[5]s[6]构成的新括号串

s[7]没有左括号与之匹配,所以w[7]=0

s[9]由于上一个右括号是s[7],它与时代脱节,所以s[9]只能将自成一家的括号串作为贡献,因为既然中间断开了就不会有在原来基础上+()生成新括号串的可能了

采用dfs递归沿着树更新结点对应的值

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<queue>

using namespace std;

typedef long long ll;

inline int read()
{
    int ans=0;
    char last=‘ ‘,ch=getchar();
    while(ch<‘0‘||ch>‘9‘) last=ch,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) ans=ans*10+ch-‘0‘,ch=getchar();
    if(last==‘-‘) ans=-ans;
    return ans;
}

const int maxn=5e5+10;
ll n,ans=0;
char s[maxn];
ll fa[maxn];
ll pre[maxn],w[maxn];

ll cnt=0,head[maxn],to[maxn<<1],nxt[maxn<<1];
void addedge(int u,int v)
{
    to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}

void dfs(int u)
{
    pre[u]=pre[fa[u]];
    if(s[u]==‘(‘) pre[u]=u;
    else if(pre[u]){
        w[u]=w[fa[pre[u]]]+1,pre[u]=pre[fa[pre[u]]];
    }
    for(int i=head[u];i;i=nxt[i]) dfs(to[i]);
}

int main()
{
    n=read();
    scanf("%s",s+1);
    for(int i=2;i<=n;i++){
        fa[i]=read();
        addedge(fa[i],i);
    }
    dfs(1);
    ans=w[1];
    for(int i=2;i<=n;i++){
        w[i]+=w[fa[i]];
        ans^=(i*w[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

-------------------------

CSP 2019 D1T2

原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/12041751.html

时间: 2024-08-30 15:04:07

P5658 括号树的相关文章

Luogu P5658 括号树|搜索+递推

CSP2019 S组D1T2 题目链接 #include<bits/stdc++.h> using namespace std; int cc,to[600000],net[600000],fr[600000],fa[600000],zhan[600000],t,n,nt[600000]; long long s[600000]; char ch[600000];string st;bool vis[600000]; void addedge(int u,int v) { cc++; to[c

CSP-S 2019 括号树

\(\text{括号树}\) 本题中合法括号串的定义如下: \(()\) 是合法括号串. 如果 \(A\) 是合法括号串,则\((A)\) 是合法括号串. 如果 \(A\),\(B\) 是合法括号串,则 \(AB\) 是合法括号串. 小 \(Q\) 定义 \(s_i\)为:将根结点到\(i\)号结点的简单路径上的括号,按结点经过顺序依次排列组成的字符串. 设\(s_i\)共有\(k_i\)个不同子串是合法括号串, 你只需要告诉小 Q 所有 \(i * k_i\)的\(xor\)值 subtask

CSP2019 括号树

Description: 给定括号树,每个节点都是 ( 或 ) ,定义节点的权值为根到该节点的简单路径所构成的括号序列中不同合法子串的个数(子串需要连续,子串所在的位置不同即为不同.)与节点编号的乘积,求所有节点权值的异或和. Solution: 闻到一股深深的 stack 气息. 懒得写了 Code: #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 5e5+1; int n; c

CSP-S2 2019 D1T2 括号树题解

说在前面的话 谨以此篇题解,纪念我初中的两年\(OI\)生涯以及不长不短的停课时光. 但愿高中还能够继续学习\(OI\)吧,也衷心希望其他\(OIer\)不要再犯类似我的错误. 题意 原题链接 给定一棵有\(n\)个节点的树,每个节点对应一个括号(左或右),需要求出从该节点到根节点的简单路径所构成的括号串中合法括号子串的数量. 其中合法括号串的定义是这样的 ()是合法括号串. 如果A是合法括号串,则(A)是合法括号串. 如果A,B是合法括号串,则AB是合法括号串. 其中\(n\le 5\time

【JZOJ6431】【luoguP5658】【CSP-S2019】括号树

description analysis 用栈维护一下树上路径未匹配的左括号,然后在树上找右括号匹配,设\(f[i]\)为\(i\)节点的贡献,\(g[i]\)是答案 为左括号可以直接继承父节点的信息,为右括号且栈非空则可以匹配,贡献值是栈顶左括号的父节点的贡献\(+1\) 这个其实就是当前子序列可以拼上左括号父亲的序列,然后每一位的答案就是父节点的答案加上当前点的贡献 code #pragma GCC optimize("O3") #pragma G++ optimize("

CSP2019游记

——by Nelson 前前夜 秋日降临. 对于我各位亲爱的高中同学们来讲,秋天,意味着井冈山,意味着期中考,意味着这繁忙的高二又过去了四分之一.而我虽然不在什么天边,却也在另一个校园里仰望同一片天空,踌躇着,准备奔向另一个战场. 夜风渐凉,再度穿上薄外套,企图用衣物掩盖内心的慌乱,还能再学到一点吗?后天能否遇上熟悉的知识点,恰好是现在眼前所及的?——或许也是徒劳吧.要不,让时间过的再快一点,现在就可以打开电脑,迎接最终的试炼?——那样的话,万一遇上本可以今天回顾的知识点,可就追悔莫及了. 明天

CSP2019题解

按照CSP题目顺序来写 格雷码 不难发现答案可以递归找到,然后每一次做即可. 代码 括号树 简单题,直接在树上搞一个栈然后回溯即可. 括号树nmsl 代码 树上的数 咕咕咕 Emiya 家今天的饭 很显然可以看出这题可以容斥,然后就可以写一个\(O(mn^3)\)的\(dp\). 然后考虑后面那两维状态可以做一个差,这样子就优化成了\(O(2mn^2)\),然后就可以过了. 代码 划分 \(\texttt{__int128}\)不香吗 代码 树的重心 代码 原文地址:https://www.cn

CSP2019 题解

CSP2019 题解 D1T1 格雷码(code) 题目传送门 https://loj.ac/problem/3208 题解 按照题意模拟就可以了. 对于第 \(i\) 位,如果 \(k \geq 2^i\) 那么这一位就是 \(1\),然后把 \(k\) 变成 \(2^{i + 1} - k - 1\).否则这一位为 \(0\),\(k\) 不变. 代码 https://loj.ac/submission/687508 D1T2 括号树(brackets) 题目传送门 https://loj.

CSP2019复赛游记

目录 Day -1 Day 0 Day 1 考前 考中 考后 做法&程序(考场做法,不能AC) 格雷码 括号树 树上的数 Day 2 考前 考中 考后 做法&程序(考场做法,不能AC) Emiya 家今天的饭 划分 树的重心 Day 3+(后记&提醒) date: 2019-11-15 前言:想直接进入正题请跳转到Day 1. Day -1 明天我就去南京了,感到非常的紧张,毕竟CSP和NOIP没有关系,没有真题可以刷(逃. 注:对于内心中难度的比较,是对于NOIP提高组的题目比较