CF936E

发布时间 2023-06-06 22:10:03作者: CelticOIer

首先考虑为什么会有一个白格子四联通的限制,这意味着没有封闭的白格子区域。

那么我们将每列都划分成一些黑格子的连续段,有相邻格子的连续段之间连边,会形成一棵树。

然后考虑如何在树上求两个格子之间的距离。可以找到他们的 \(lca\) 然后把 \(lca\) 的每个格子放进队列里进行一次 \(bfs\) ,得到两个点分别到 \(lca\) 处最短路径所对应的格子,那两个点的距离就是两个点的最短路再加上他们在 \(lca\) 对应格子的距离。

那么考虑建出点分树,维护每个祖先的贡献。因为是最短距离所以走重复路径不影响答案,可以直接对这个祖先的整个子树一起处理。在点分治的时候预先把每个点的子树 \(bfs\) 好,贡献只剩下一个对应格子的距离,这是一个绝对值的形式。讨论一下绝对值,把绝对值打开,只需要每个节点维护两个树状数组,一个是绝对值中负的贡献,一个是正的贡献。查询只需要查询负的前缀最小值和正的后缀最小值就行了。

有一些卡常,建议不要在线处理询问,把每个修改和查询挂到每个祖先上,最后一遍点分治处理所有答案。

还有一些细节,比如 \(bfs\) 的时候先预处理每个点的相邻点,就只需要存编号不用存坐标,可以不用哈希表。

https://codeforces.com/contest/936/submission/208707254