题解:P13019 [GESP202506 八级] 树上旅行

本题的核心在于将“连续若干次向父节点跳”与“连续若干次向最小子节点跳”两类操作,用倍增压缩到对数级。设 \(\text{up}[j][u]\) 表示从结点 \(u\) 连续向父亲跳 \(2^{j}\) 步后的结点,\(\text{dn}[j][u]\) 表示从 \(u\) 连续向编号最小的子结点跳 \(2^{j}\) 步后的结点。先扫描输入得到每个结点的父亲 \(p_u\) 的同时,用一次比较即可记录每个非叶结点的最小子结点 \(\text{mc}[u]\);若 \(u\) 是叶子,就令 \(\text{mc}[u]=u\)。于是有 \(\text{up}[0][u]=p_u\)\(\text{dn}[0][u]=\text{mc}[u]\)。再利用倍增递推:\(\text{up}[j][u]=\text{up}[j-1][\,\text{up}[j-1][u]\,]\)\(\text{dn}[j][u]=\text{dn}[j-1][\,\text{dn}[j-1][u]\,]\)。因为 \(n\le10^{5}\),取 \(18\) 层即可覆盖所有距离。

回答一次旅行时,顺序扫描移动序列。若当前整数 \(x>0\),把 \(x\) 的二进制拆分为若干位,第 \(b\) 位为 \(1\) 则令 \(u=\text{up}[b][u]\);若 \(x<0\),则令 \(u=\text{dn}[b][u]\)。根的父亲被设为自身,叶子的最小子也设为自身,因此到达根或叶后继续“跳”也会停在原处,正好符合题意“无法再移动就保持不动”。

预处理两张倍增表需要 \(O(n\log n)\);处理全部旅行需要 \(O\bigl((\sum k_i)\log n\bigr)\)

建议学习:【模板】最近公共祖先(LCA)

link

posted @ 2025-06-30 18:00  薛儒浩  阅读(108)  评论(0)    收藏  举报