【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\)。