UOJ #841. 龙门探宝
我一直以为这个东西只能树上圆理论解决啊?没想到有极度优秀的结论。
考虑从小到大对 \(r\) 扫描线,维护每个 \(l\) 处直径的变化,对于长度相同的直径,我们添加第二维比较使其不同。
有结论:记 \(f(l,r)\) 直径为 \((u,v)\),若加入 \(r+1\) 之后,\(dist(u,v)<dist(u,r+1)\),且 \(f(l-1,r)\) 直径的两端点之一也包含 \(v\),则 \(v\) 同样会被替换成 \(r+1\),且不论另一端点是什么,直径的变化量也为 \(dist(u,r+1)-dist(u,v)\)。
证明考虑 \((u,v)\) 与 \((u,r+1)\) 的交点 \(p\),记 \(l_1=dist(p,u),l_2=dist(p,v),l_3=dist(p,r+1)\),有 \(l_1>l_2,l_3>l_2\),也即 \(p\) 实际上在 \((u,v)\) 路径中点偏 \(v\) 的一边。
显然我们只需要考虑 \(f(l-1,r)\) 中 \(u\) 被替换成 \(w\) 的情况,这时交点 \(q\) 在路径 \((u,v)\) 中点靠 \(u\) 的一边,这样不会影响中点到 \(v\) 这段的路径,则 \((r+1,w)\) 与 \((w,v)\) 路径交点仍为 \(p\),变化量还是这个值。
有了这个结论,我们维护每个点作为直径端点在哪个区间里出现了,每次会把一个区间里的点全部替换掉,记势能为 \(2\) 倍区间个数加上完全包含的区间对数即可说明每次操作至少减少一次势能,而总势能只会增加 \(2n\) 次,每次操作需要 \(3\) 次查询,所以只需要至多 \(6n\) 次查询即可完成。
时间复杂度 \(O(n\log n)\),因为需要记忆化。