[DS记录]P5529 [Ynoi2012] 梦断 SCOI2017

command_block

2021-07-07 15:15:16

Personal

**题意** : 给出一棵 $n$ 个点的树,每个点有一个 $1\sim k$ 内的颜色。 定义同色块为保留同色边后的连通块。 支持下列操作 : - 修改某个点的颜色。 - 修改点 $u$ 所在同色块的颜色。 - 查询点 $u$ 所在同色块的最深点与最浅点的深度差。 $n,m\leq 10^5,k\leq 30$ ,时限$\texttt{1s}$ ,空限$\texttt{125M}$。 ------------ 蒟蒻第一次写 ETT ,本题细节较多,讲得不好请见谅 qwq 称 $u$ 与父亲相连的边为“向上边”,称 $u$ 与直接儿子相连的边为“向下边”。 - ## 不考虑操作二 - ### ETT 与边连通块 将一条边的颜色定义为较深的端点的颜色,用 **ETT** 维护同色**边连通块**。 (ETT 维护的是括号序列,一对括号可以看做一条边的一进一出) ![](https://cdn.luogu.com.cn/upload/image_hosting/0lezravu.png) 图中蓝框是一个“边连通块”的范围,而红框是一个题目中“同色块”的范围,注意其中的不同之处。 - ## findrt 考虑如何利用这个结构找出某个点所在的同色块的最浅点。 在每棵 ETT (代表一个边联通块)的根记下该边联通块的最浅点(如图黑点)。 对于点 $u$ ,只需要找出 $u$ 所在的 ETT 的根,然后找出边联通块最浅点 $v$ ,再查询 $u$ 到 $v$ 的路径上倒数第二个点即可得知答案。 - ## 查询 先找出 $u$ 的同色块的最浅点 $v$。 将 $v$ 的向上边的一对括号内部的东西 $\rm spilt$ 出来,这就是 $u$ 所在的同色块。 在 ETT 中维护子树最深点,容易回答询问。 - ## 单点修改 修改点 $v$ 的颜色,相当于修改边 $l=u\rightarrow v$ ( $u$ 浅 $v$ 深)的颜色。 记原来的颜色为 $c_0$ ,新的颜色为 $c_1$。(需要保证 $c_0\neq c_1$) 记 $son_{u,c}$ 表示 $u$ 的任意一个颜色为 $c$ 的儿子。 每次修改后只需要更新 $son_v$ ,用 `std::set` 维护,复杂度是 $O(\log)$ 的。空间也可以做到线性。 将边 $l$ 的两个括号从所在的 ETT 上删除,将原来的 ETT 分为三个部分 : ![](https://cdn.luogu.com.cn/upload/image_hosting/7mcl988a.png?x-oss-process=image/resize,m_lfit,h_300) 考虑 $v$ 处新产生的连通性,找出 $son_{v,c_1}$ ,将其所在的 ETT 连接为 $l$ 的子树。(塞入 $l$ 的一对括号之中) 考虑 $u$ 处新产生的连通性,尝试找到 $t=son_{u,c_1}$ ,若存在,则将 $l$ 的 ETT 插入 $t$ 所在的 ETT 中 $t$ 右括号的右侧(表示并列)。 - ## 考虑操作二 - ## 对 $son$ 的修正 首先对 $son$ 稍作修正。若 $u$ 点的颜色为 $c$ ,钦定 $son_{u,c}$ 为未定义,否则操作二就会影响到大量 $son$ 的取值。 观察我们实际上用到 $son$ 的场合。 将 $u\rightarrow v$ 的颜色从 $c_0$ 改为 $c_1$ 时 : - 考虑 $v$ 处新产生的连通性,找出 $son_{v,c_1}$ …… 此时 $v$ 的颜色是 $c_0\neq c_1$ ,无影响。 - 考虑 $u$ 处新产生的连通性,尝试找到 $t=son_{u,c_1}$ …… 此时 $u$ 的颜色可能是 $c_1$ ,但此时直接令 $t=u$ 即可处理。 这又需要支持查询某点的颜色,类似上文对边联通块最浅点的处理,直接记在 ETT 的根上。 - ## 同色块修改 首先将需要修改的同色块 $\rm spilt$ 出来,设颜色被改为 $c$。 记同色块的最浅点为 $v$ ,$v$ 的父亲为 $u$ 。 考虑 $u$ 处新增的连通性,这个和单点类似,不再赘述。 除了 $u$ ,也会有其他地方产生新的连通性。我们需要找出连通块中所有 存在颜色为 $c$ 的向下边的点。 对于一个这样的点 $v$ ,找出 $son_{v,c}$ ($v$ 原来的颜色必不是 $c$),将其所在的 ETT 连接为 $v$ 的子树。 在 ETT 中用 `uint` 状压“子树内是否存在拥有颜色 $1\sim k$ 的向下边的点” ,然后大力搜索,即可快速找到所有的 $v$。 记 $c_u$ 为 {$u$ **和**直接儿子} 中的不同颜色数。我们发现,找出的 $v$ 都满足 $c_v\geq 2$ ,而且操作后 $c_v$ 至少减少 $1$。 $c$ 的初始和为 $O(n)$ ,而每次单点修改只会增大 $O(1)$ ,故复杂度均摊正确。 总时间复杂度为 $O(n\log n)$,空间复杂度为 $O(n)$。 ```cpp ```