APIO2020 简要题解

现场得分 \(28 + 100 + 26 = 154\)

\(A\)
首先 , 考虑动态规划。
\(f_{i,j}\) 表示前 \(i\) 段墙壁 , 交给第 \(j\) 个及之前的承包商粉刷 , 最多匹配的长度。
注意到 \(f_{i}\) 之和 \(f_{i - 1}\) 有关 , 因此可以用滚动数组来优化空间复杂度。
这样就求出了第 \([i - m + 1 , i]\) 这段区间的墙壁是否可以被某个承包商粉刷。
将所有可以的位置排序 , 然后贪心地尽可能往后放即可。
时间复杂度 : \(O(N)\)
代码 : https://loj.ac/submission/922889

\(B\)
首先考虑一个 \(O(NMlogN)\) 的做法。
二分答案 \(mid\) , 保留图中权值不超过 \(mid\) 的边 , 如果图中有环或度数超过 \(2\) 的点 , 那么就符合要求。
这是因为可以让一辆车在一个节点处停留 , 等另一辆车到达目的地后再继续开。
这样可以得到 \(37\) 分。
接着 , 考虑克鲁斯卡尔重构树 , 对于重构树上每个节点记一个权值 , 代表的是这个联通块最早符合要求是什么时候。
回答询问时 , 先求出 \(u\)\(v\) 的最近公共祖先 。 再倍增至第一个权值非空的节点 , 即可。
时间复杂度 : \(O((N + M)logN)\)
代码在考场上。

\(C\)

首先找出这棵树的重心。 这需要花费 \(2M\) 次操作。
注意到每个点的度数不超过 \(3\)
如果重心的度数为 \(2\) , 由重心的性质 , 两棵子树大小差不超过 \(1\) , 每次取不同于上次所选的那棵子树中 , 剩下的深度最大的节点来构造出一种合法方案。
如果度数为 \(3\) , 延续刚才的思路 , 每次取不同于上次所选的两棵子树中剩余深度最大的节点。
这样做必然有一时刻 , 某两棵子树的大小和等于另一棵子树的大小。 其正确性在于 :
记函数 \(V = 2 \cdot max{size} - sum{size}\) , 由重心的性质得到函数 \(V\) 的初值小于 \(0\)
这个函数在每次操作后的变化量为 \(1\) , 因此一定存在某一时刻满足 \(V = 0\)
因此 , 在这个时刻到来时 , 将两棵较小的子树合并 , 用度数等于 \(2\) 的方法处理即可。
总操作数 \(4M\)。时间复杂度 : \(O(NlogN)\)
代码 : https://loj.ac/submission/926697

posted @ 2020-09-14 17:26  evenbao  阅读(522)  评论(0编辑  收藏  举报