Foreword\text{Foreword}Foreword
肝了一下午+一晚上的码农题…
(主要就是在 debug,LCT 太难 de 了…)
感谢 @M_sea,在调无可调认为LCT会不会不可做时,我看到了他的题解,几乎一样的思路,给了我继续调下去的信心。
Solution\text{Solution}Solution
第一感就是割点 LCT 的感觉。(为什么都说这是平衡树板题啊…)
细化一下,把每个格点分成左上、右上、左下、右下四个点,每条边分成两边两个点,在可以直接走过的相邻点直接连边,那么整张图就会变成若干个环。
询问就是要求给出两点在环上钦定方向的距离。
对于修改,一个避免分讨的实现方法是把修改格边涉及到所有点之间的边 cut 掉,修改格边的存在状态后,再按照新的状态把对应的点 link 回去。
还有一个问题:LCT是无法维护环的,怎么办?
一个比较直观的想法是:随便选一条边 cut 掉(称为特殊边),这样就变成一条链了。询问的时候,“钦定的方向”要么是 split 出的实链的长度,要么是其补集,常规套路记录实链大小和虚子树大小即可。
但这样修改的时候会出问题:如果修改边使两个环合并为一个环,那么这个环上就会有两条特殊边,那么最终的 LCT 形态就会变得不连通了…
也有解决方法:在合并环之前把各自的特殊边 link 回去,合并完之后自然就只会出现一条新的特殊边(即合并失败的边)。
所以我们现在还需要记录一下每个环的特殊边是什么,通过 LCT 打标记即可维护。
于是本题就做完了。
(我调了一晚上的坑点:当特殊边被修改的格边状态涉及到时,不应该额外 link 特殊边,因为修改格边状态后可能这条边本身可能就已经不复存在了!)
Code\text{Code}Code
代码调调补补变得又长又丑,就放剪切板吧。