你为何要读这篇文章(本文涉及的内容):本题(包括加强版)的算法的详细描述与贪心的正确性证实。算法
2020-03-12 edit:优化
偶然翻到这篇博文,感受本身写的题解是真的太毒瘤了……连我本身都看不懂本身写了啥。spa
作了一点修改与补充,enjoy!排序
二分答案+贪心。部署
下文中,咱们:get
考虑\(leaf(u)\)被控制的充分必要条件:it
为了简化问题,咱们先考虑在二分到\(mid\)时,哪些军队的位置是固定的。io
显然,对于那些“不能到达根节点”,即\(d(x,1)>mid\)的军队\(x\),尽可能向上移动是最优的。class
那么,能够用倍增在\(O(\log n)\)时间内处理出这些军队的最终位置,能够经过 DFS 求出根的哪些儿子的子树(的叶节点)没有被(彻底)控制,设其集合为\(S_1\subseteq son(1)\)。(显然,其余节点都部署在根的儿子上)方法
以后,就是考虑可以到达根\(1\)的节点如何部署的问题了。因为离根越远的儿子越难知足,根据贪心的原则,优先考虑离根最远的儿子\(u\):
一个实现上的优化:若\(u\)的子树内能够到达\(u\)且离\(u\)最远的军队已经被部署,则\(u\)的子树内已经没有未被部署的军队(由于老是由近到远选择军队部署),直接转到2便可。
若某个可行解里\(x\)部署到了\(v\in S_1,v\ne u\)上(或者没有部署,此时正确性是显然的),考虑该解中,部署在\(u\)的军队\(x'\),则其能够与\(x\)交换部署的位置。咱们来证实这一点。
有假设,显然有\(d(x',u)\le mid,d(x,v)\le mid\)。此外,\(x\)必定能够部署到\(u\)上,有\(d(x,u)\le mid\)。
故咱们只须要说明\(x'\)能够部署在\(v\)上,即\(d(x',v)\le mid\)便可。咱们来分状况说明这一点:
如下的证实为了避免把行内公式写得太长,跳过了一些步骤。
具体证实最多只需用到\(d(x,y)\le d(x,z)+d(z,w)\),就做为留给读者的练习了~
那么(基本上只须要按照上面的描述)直接写就能够了。(注意细节……这题毕竟是个紫题……)
增强版的数据要求算法复杂度只能一个\(\log\),怎么办?
显然,二分答案这一步是没办法去掉的……只能尝试把判断可行性优化到\(O(n)\)。
注意到在\(mid\)时间内处理出(不)能够到\(1\)的军队是简单的:预先处理出全部\(d(x,1)\)并排序,则答案为一个它的一个前缀。
考虑不倍增怎么求\(1\)的“哪些\(u\in son(v)\)的子树被控制”。换句话说,对于一个节点\(u\in son(1)\),咱们须要知道:
标记那些\(d(x,1)>mid\)的军队\(x\)(在树上的位置),在 DFS 到\(u\)时显然能够全部\(v\in son(u)\)的子树是否被控制,以及节点\(u\)距离最近的\(x\in tree(u)\)的距离,判断是否有\(d(x,u)\le mid\)便可。
LOJ最短代码 (写文章时)