限于打摆时间太长和模拟赛太多,没有时间把它更完了,题目应该只有 1 个没写了
IOI2015 town
使用两遍 \(\rm DFS\) 求直径的手段计算得到直径 \((x,y)\) 某个端点 \(y\) 和另外一个圆点到所有点的距离,此时可以计算每个点 \(z\) 到直径的距离,也就是使用 \((z,x),(z,y)\) 减去 \((x,y)\) 再除二
\(\arg \min r(C)\) 一定在直径上,第一问可以解决,同时可以找出有几个点取到最小值(最多两个)
先处理只有一个点 \(p\) 取到最小值的情况:
对于和直径作垂线得到的垂足不为 \(p\) 的可以通过到 \(x\) 的距离分到两边子树上
对于其他点 \(s,t\) 而言,判断是否处于同一个子树的方法是判断 \(dis(s,t)\) 和 \(s,t\) 到直径距离之和的大小关系,那么甚至不用管上一行所说,直接做摩尔投票再验证一遍询问次数就是 \(4n\)
由于只关注“是不是再同一棵子树”,那么可以在第一遍做摩尔投票的时候记录相等关系直接算数目
如果这个 \(p\) 满足一定不需要把询问次数使用完(不相等的直接跳过不问,跳的次数是非这个子树元素数量,小于 \(\frac n2\)),否则询问次数用完的时候直接判定不存在即可
两个点取到最小值时直接判定是不是非移动方向一侧子树大小满足条件,因为移动向这侧都被冲散了