原题链接

简要题意:

求出以从每个节点到根形成的括号序列的合法对数。

算法一

观察到 \(n \leq 8\) ,所以我们可以用 纯粹的暴力

用 \(O(n)\) 时间得出当前节点到根的字符串。

然后 \(O(n^2)\) 枚举子串。

再用 \(O(n)\) 暴力判断(用栈)。

时间复杂度: \(O(n^5)\).

实际得分: \(10pts\).

优化一

用 \(s_i\) 表示 \(i\) 号节点对应的括号。

用 \(h_i\) 表示当前节点到根的字符串。

用 \(fa_i\) 表示当前节点的父亲编号。

则:

\[h_i = h_{fa_i} + s_i
\]

由此,\(O(1)\) 推出字符串。

然后 \(O(n^2)\) 枚举子串,\(O(n)\) 验证。

时间复杂度: \(O(n^4)\)

实际得分: \(10pts\).

优化二

同样 \(O(1)\) 推出字符串。

下面,我们用 \(f_i\) 表示从第 \(i\) 号节点到根形成的括号序列的合法对数。

那么,显然存在:

\(f_i \geq f_{fa_i}\)

也就是说,我们只需要考虑以 \(i\) 号节点结尾的子串的贡献。

这样,我们枚举子串的时间复杂度降为 \(O(n)\),判断降为 \(O(n)\).

总时间复杂度: \(O(n^3)\)

实际得分:\(20pts\)

优化三

显然,我们需要摆脱枚举子串,而用另一些东西直接维护。

\[ h_i=
\begin{cases}
h_{fa_i},s_i = \text{(} \\
h_{fa_{g_i}}, s_i = \text{)} \\
\end{cases}
\]

其中, \(g_i\) 表示从当前节点开始,到根的路径上第一个(从下往上数)未匹配的左括号。

如果 \(s_i = \text{(}\) ,显然以当前节点结尾没有合法子串。

如果 \(s_i = \text{)}\) , 则找到它可以匹配的第一个左括号,然后记录那个左括号父亲的值(即前面的值)即可。

那么,\(g_i\) 如何维护呢?

\[g_i =
\begin{cases}
i , s_i = \text{(} \\
g_{fa_i} , s_i = \text{)} \\
\end{cases}
\]

这也是显然的。

那么,我们可以做到 \(O(n)\) 时间维护这所有的东西。

总时间复杂度: \(O(n)\).

实际得分: \(100pts\).

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std; const int N=5e5+1;
typedef long long ll; inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;} char s[N];
int n; ll ans;
ll f[N],g[N],fa[N];
vector<int>G[N];
// f[i] 为 当前节点的贡献值
// g[i] 为 从当前节点起,第一个没匹配的左括号的编号 inline void dfs(int dep) {
g[dep]=g[fa[dep]];
if(s[dep]=='(') g[dep]=dep;
else if(g[dep]) f[dep]=f[fa[g[dep]]]+1,g[dep]=g[fa[g[dep]]]; //维护
for(int i=0;i<G[dep].size();i++) dfs(G[dep][i]); //递归下去
} int main(){
n=read(); scanf("%s",s+1); //一个技巧,让字符串下标从 1 开始
for(int i=2,t;i<=n;i++) {
t=read(); fa[i]=t;
G[t].push_back(i); //存儿子节点编号
} dfs(1);
ans=f[1]; for(int i=2;i<=n;i++)
f[i]+=f[fa[i]],ans^=(i*f[i]); //我们把父亲的值放到最后算,避免出错
printf("%lld\n",ans);
return 0;
}

洛谷 P5658 括号树 题解的更多相关文章

  1. 洛谷 P5658 括号树

    \(50pts\) #include <cstdio> #include <cstring> #include <iostream> #include <al ...

  2. P5658 括号树

    P5658 括号树 题解 太菜了啥都不会写只能水5分数据 啥都不会写只能翻题解  题解大大我错了 我们手动找一下规律 我们设 w[ i ] 为从根节点到结点 i 对答案的贡献,也就是走到结点 i ,合 ...

  3. 2021.08.09 P5658 括号树(树形结构)

    2021.08.09 P5658 括号树(树形结构) [P5658 CSP-S2019] 括号树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 太长,在链接中. 分析及代码 ...

  4. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

  5. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  6. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  7. 洛谷P2312 解方程题解

    洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...

  8. 洛谷P1577 切绳子题解

    洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...

  9. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

随机推荐

  1. 年薪5w和50w的人,区别到底在哪?

    年薪5w和50w的人,区别到底在哪? 2017-02-22 阿青 360投资圈 文/ 阿青 许多人在职场摸爬滚打很多年并不顺利,薪酬一直上不去.职场鸡汤喝了不少,也掌握了不少职场技能,工作经验也颇为丰 ...

  2. Chrome 插件安装时报错: "CRX_HEADER_INVALID"

    1. 将 crx 插件后缀名改为 rar 2. 解压 rar 包 3. 进入浏览器 1). 点击Chrome浏览器地址栏最右边的三个点 --> 更多工具 --> 扩展插件 --> 点 ...

  3. 全差分运算放大器ADA4930的分析(1)

    AD转换芯片的模拟信号输入端方式为:全差分.伪差分.单端输入,其中全差分输入的效果最佳,现阶段ADC转换器为了提高其性能,建议用户使用全差分的输入方式.(AD7982.ADS8317等都能实现信号的全 ...

  4. 前端每日实战:111# 视频演示如何用纯 CSS 创作一只艺术的鸭子

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/aaoveW 可交互视频 此视频是可 ...

  5. jQuery上传文件按钮美化

    效果图如下: 思路: 1:打开文件设置为透明,外面包一层标签,给标签设置颜色背景,给人点击浏览其实是点击打开文件的错觉.(给外标签相对定位,打开文件标签绝对定位). 2:点击浏览后,选择了文件,就把文 ...

  6. MySQL 【教程一】

    前言 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库. 每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据. 我们也可以将数据存 ...

  7. SpringBoot2整合Shiro报错 UnavailableSecurityManagerException: No SecurityManager accessible to the calling code 【已解决】

    SpringBoot集成Shiro报错 UnavailableSecurityManagerException: No SecurityManager accessible to the callin ...

  8. [日志分析]Graylog2采集mysql慢日志

    之前聊了一下graylog如何采集nginx日志,为此我介绍了两种采集方法(主动和被动),让大家对graylog日志采集有了一个大致的了解. 从日志收集这个角度,graylog提供了多样性和灵活性,大 ...

  9. c#序列化和反系列化json与类型对象转换

    先添加程序集:  System.Web.Extensions(在 System.Web.Extensions.dll 中) 引用:using System.Web.Script.Serializati ...

  10. 浅谈ASP.NET Core中的DI

    DI的一些事 传送门马丁大叔的文章 什么是依赖注入(DI: Dependency Injection)?     依赖注入(DI)是一种面向对象的软件设计模式,主要是帮助开发人员开发出松耦合的应用程序 ...