【IOI2015】Towns

一个简单的想法是先用 \(2n - 3\) 次求直径 \(A, B\)\(D\),每次距离最远的点。然后中心一定在直径上。

然后由于度数 \(> 3\) ,可以找到每个叶子在这条链上的相应位置( \(i\) 所在到直径最近的点),就用 \(a_i = (d_{i, A} +d_{i,b} - D) / 2\) 可以得到的距离,然后 \(d_{i, A} - a_i\) 可以得到在直径的相对位置。这样就 \(3n - 4\) 解决了第一问。

度数 \(= 3\) 是好做的,所以关键就是要找出相应位置在中心的那些点,分别属于中心的儿子里。

考虑如果分属不同集合那就是 $LCA = $ 中心,那就是 \(a_i + a_j = d_{i,j}\) ,这样就能判了。

考虑相当于这里每个点颜色是属于中心的哪个儿子,要找是否存在绝对众数。用哪个 \(O(1)\) 主元素的方法,就是每次维护一个 \(cnt\) 和当前颜色的一个点,和现在一样就是 \(+1\),不一样就 \(-1\),只有最后剩下的可能是主元素。最后还要再扫一遍,这样第二个部分就是 \(2n\) 的。

这样 \(5n\) 就很逊,然后就不会了。

考虑对着第二部分优化,定义一次过程是 \(cnt = 0\) 到下一个 \(cnt = 0\) 的过程。仔细分析一下,主元素法的过程问的事实上是 $n\ - $ 过程数。然后每个过程数有一半是相同的,你花费过程数把那一半相同的问了,然后再暴力问后一半,那这个过程其实不超过 \(1.5n\) 的。

\(4.5n\) 很蠢。

考虑对着前面优化,一直没用到 \(0\) 到所有点的距离,很浪费!!!1

其实我们发现如果要找中心,不一定必须把直径抠出来。比如 \(0\) 的最远点是 \(A\)\(0 \sim A\) 的链其实肯定有俩中心!我们可以先整出来到所有点到 \(0 \sim A\) 这条链的距离,可以整出来最近点到 \(A\) 的距离,这里面肯定有属于中心的,就把中心数到了。

然后接下来过程就跟前面差不多,就是考虑 \(0\) 那一端有一段不在直径上,考虑可以和 \(R\) 取个 \(\min\),太远就视为在中心,做的过程和之前一样,这样就省去了问 \(B\) 到每个点的距离。

\(3.5n\)

code

posted @ 2022-07-18 22:26  DMoRanSky  阅读(220)  评论(0编辑  收藏  举报