缝合怪

如题,缝合怪。

题目链接

前置知识:题目标签里的所有算法,并确保透彻掌握。

距离 \(u\) 不超过 \(k\) 的点集(或距离 \(u\) 恰好为 \(k\) 的点集)称作“树上圆问题”,是点分治的模板;最大点异或是 01trie 的模板。但是点分治还需要一些奇怪的约束,导致还要多一个 cdq 分治的 log。

考虑当前在分治中心 \(rt\) ,结点深度用 \(dep\) 表示。处理到点 \(u\) 上的一个询问,参数为 \(k\)\(x\),那么我们需要找一个点 \(v\) ,满足:

  1. \(v\) 与点 \(u\) 不在同一子树内。
  2. \(dep_v+dep_u\leq k\) ,即 \(dep_v\leq k-dep_u\)
  3. \(a_v \text{xor}{x}\) 取得最大值。

只考虑 \(2,3\) 的话,显然是一个 可持久化01trie 可解决的问题,按照深度插入即可。关于点分治要求的 \(1\) ,一般有两种处理方法:

  1. 删除子树:把分治块内的点全部插入,处理该子树时,把该子树中的点暴力删除,处理完再加回来。但是众所周知,可持久化数据结构不支持删除。舍去。
  2. 处理前后缀:按子树顺序与逆序插入两次,处理该子树时,在前缀与后缀中分别查询。但是 可持久化01trie 强制要求按照深度插入,舍去。

怎么办呢?我们想办法一般地理解 \(1\) 限制。dfs 当前连通块并记下每个点的 \(dfn\) 序,记进入 \(u\) 子树的 \(dfn\)\(st_u\),出去的为 \(ed_u\),那么 \(1\) 就表述为:

\[(dfn_v<st_u)\lor(dfn_v>ed_u) \]

这个可以通过两次 cdq 分治实现。具体地,以 \(dfn_v<st_u\) 为例:

按照(结点的 \(dfn\) 序,询问的 \(st\) 值)分治。处理时按照 (结点的 \(dep\),询问的 \(k-dep\))排序。再加上普通的 01trie 就好了。

因为这题过于模板,加上码量会很大,数据也会比较难造(很可能三只 log 跑不过 n^2),因此暂时就丢在这里了。希望大家可以通过这题加强对这三个算法的理解。

如果有更优的做法,请务必告知。

posted @ 2022-06-02 19:57  Sherlockk  阅读(41)  评论(0)    收藏  举报