【日常训练】「CSP-S 2019」括号树plus

CLYZ 学长学姐们留下来的题,感谢 + 膜拜。

Description

题目背景

本题中合法括号串的定义如下:

  1. () 是合法括号串;
  2. 如果 A 是合法括号串,则 (A) 是合法括号串。
  3. 如果 AB 是合法括号串,则 AB 是合法括号串。

本题中子串不同的子串的定义如下:

  1. 字符串 S 的子串是 S连续的任意个字符组成的字符串。S 的子串可用起始位置 l 与终止位置 r 来表示,记为 S(l,r)1lr|S||S| 表示 S 的长度)。
  2. S 的两个子串视作不同当且仅当它们本质不同

题目描述

一个大小为 n 的树包含 n 个结点和 n1 条边,每条边连接两个结点,且任意两个结点间有且仅有一条简单路径互相可达。

小 Q 是一个充满好奇心的小朋友,有一天他在上学的路上碰见了一个大小为 n 的树,树上结点从 1n 编号,1 号结点为树的根。除 1 号结点外,每个结点有一个父亲结点,u2un)号结点的父亲为 fu1fu<u)号结点。

小 Q 发现这个树的每个结点上恰有一个括号,可能是 ()。小 Q 定义 si 为:将根结点到 i 号结点的简单路径上的括号,按结点经过顺序依次排列组成的字符串。

显然 si 是个括号串,但不一定是合法括号串,因此现在小 Q 想对所有的 i1in)求出,si 中有多少个互不相同的子串合法括号串

这个问题难倒了小 Q,他只好向你求助。设 si 共有 ki 个不同子串是合法括号串,你只需要告诉小 Q 所有 i×ki 的异或和,即:

(1×k1) xor (2×k2) xor (3×k3) xor  xor (n×kn)

其中 xor 是位异或运算。

数据范围:1n5×105
时空限制:5000 ms/512 MiB

Solution

采用增量法。对树进行 DFS,每次计算以 u 为最低点时的答案。

由于要求本质不同,对于一个串 s[u..tu],如果其在 s[fau..1] 中作为子串出现,则这样的串是不能计入答案的。

考虑求一个深度最小的 tu,相当于是在 fau1 的路径上选一个点 v,使得 LCP(s[u..1],s[v..1]) 最大。
在树上做一遍 SA,这相当于是在 fau1 的路径上,找 rku 的前驱后继。用 std::set 维护即可。

考虑求在 fatu1 的路径上,有多少个点 v 使得 s[u..v] 是一个合法括号串。
将左右括号转换为 ±1 做一个前缀和。用倍增找出可行范围后,在 std::vector 上二分维护即可。

时间复杂度 O(nlogn)

posted @   Calculatelove  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示