P5321 [BJOI2019]送别(LCT)

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

代码调调补补变得又长又丑,就放剪切板吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值