题解【CF1149C Tree Generator™】

· · 题解

CF1149C Tree Generator™

不一定更好的阅读体验

牛逼题 & ZROI Day3 数据结构选讲。

来一波详细的题解。

当时和 \texttt{ys}\texttt{hy} 还有小猴子讨论了半天,一直认为是最大子段和很激动直接就在群里说了,结果被喷了,然后一波周折群友觉得这是十分正确的,然后一波周折又被喷了(

考虑把 ( 看成深度 +1) 看成深度 -1,那么就可以把括号序列看成一个 +1-1 的序列。

考虑一条路径的长度如何算,对于一段 u\to \operatorname{lca}(u,v)\to v 的路径,在括号序列上肯定会被表示成形如 )...)(...( 的一段,路径长度为 ( 括号数量 + ) 括号数量。

但是,如果路径上还会有一个子树,比如形如 )..()..)(..(() 是需要忽略不计的。

由此我们得到结论:括号序列上任何一个子区间,去掉所有匹配的括号后,得到的括号序列一定是树上一条链。如果用权值表示法来表示,你会发现其实匹配的括号根本不用管,因为一个 (+1) 和一个 (-1) 都消掉了,如果我们称 )( 为分界点,( 右边的部分为右区间,) 左边的部分为左区间,那么这条路径的长度为,右区间的权值和 + 左区间权值和的相反数,因为左区间的 ) 我们表示成了 -1,现在需要算成 1 的长度。

对此,我们又得到一个结论:对于所有子区间,找到一个分界点,右区间权值和 - 左区间权值和的最大值,为这个子区间的路径长度最大值。

那么显然,树的直径是对于所有子区间,找到一个分界点后的权值最大值。

交换字符可以看成 \Theta(1) 的修改,那么很自然地想到用线段树来维护这个东西,且类似于最大子段和。

维护区间答案 \text{ans},后缀最大值 \text{sm},后缀最小值 \text{sn},前缀最大值 \text{pm},前缀最小值 \text{pn}

但这样是不足以转移的,比如左区间是 ))) 右区间是 ))(,你完全可以一起拼一块儿。

所以我们还要维护一下,紧靠左端点的答案最大值 \text{lm},紧靠右端点答案最大值 \text{rm},紧靠左右端点的答案最大值 \text{lrm},以及区间和 \text{sum}

考虑 \texttt{pushup} 的过程,设 u 的左右儿子分别为 u_0u_1

前缀最小值 / 最大值都可以通过区间和来转移,考虑 \text{lm} 的转移,首先可以直接继承 \text{lm}_{u_0},还让左区间紧靠左右端点的答案再拼上右端点的 (..(,即 \text{lrm}_{u_0}+\text{pm}_{u_1},还可以是右区间选择一个紧靠左端点的答案段 )..)(..(,然后左区间全部选择,只不过这里需要注意取反,\text{lm}_{u_1}-\text{sum}_{u_0}\text{rm} 是同理的。

最后还剩一个 $\text{lrm}$,这个很简单,只需要一个区间选择 $\text{lrm}$ 另一个区间选择 $\text{sum}$,同样注意变号的问题:$\text{lrm}_u\leftarrow\max(\text{lrm}_{u_0}+\text{sum}_{u_1},\text{lrm}_{u_1}-\text{sum}_{u_0})$。 这样就都处理完毕啦。 [**code**](https://codeforces.com/contest/1149/submission/174713590)。