APIO 2020 题解

A - Painting Walls

可以发现,题中所谓的要求作为一个二元组 \((x,y)\),看上去有 \(O(NM)\) 个,没算上判定的时间就已经远远超出承受范围了。但思考得知,我们要求本质上是刷这 \(N\) 个墙壁,而每次刷的区间长度固定为 \(M\),也就是说只有 \(O(N)\) 个本质不同的刷墙方法,这成为我们的突破口。

换言之,我们需要对于每个 \(i\) 得到是否存在合法的从 \(i\) 开始的刷墙要求。考虑一个朴素的动态规划:\(f(i,j)\) 表示从 \(i\) 这堵墙开始,如果第一个指派的承包商为 \(j\),按题意循环最多可以连着刷多少。那么显然:

\[\forall j\in B_{C_i} : f(i,j)=\begin{cases} f(i+1,(j+1)\bmod M)+1 & (j+1)\bmod M\in B_{C_{i+1}} \\ 1 & \text{otherwise.} \end{cases} \]

最后对于每个 \(i\) 都检查是否存在一个 \(j\) 满足 \(f(i,j)\ge M\) 即可。

但这个 dp 貌似是 \(O(NM)\) 的,实则不然,因为有 \(\sum f^2(k) \le 4\cdot 10^5\),也就是说 \(f(k)\le \sqrt {4\cdot 10^5}\),这意味着每个 \(i\) 中有效的 \(j\) 并不多,那不需要存下所有状态就能在可承受的时间内 AC 了,复杂度 \(O(N\cdot \sqrt{\sum f^2(k)})\)

参考实现:https://loj.ac/s/1127905

B - Swapping Cities

首先考虑无解的充要条件是什么。简单手玩可以发现具体的方案要么就是绕出一个圈,要么就找一个岔路避让,而唯一的不可行方案是链状的图。而一个连通图是链,当且仅当其上没有超过 \(2\) 度的点其无环。

如果是一辆车,那答案就是最小瓶颈路。考虑这里很可能就是最小瓶颈路的变式,尝试 Kruskal 重构树。首先对于询问 \(X,Y\),答案不可能低于最小瓶颈路,那可以先找到 \(X,Y\) 在重构树上的 LCA \(L\)。假如说 \(L\) 所表示的连通块已经不是链了,那显然 \(L\) 对应的边权就是答案。反之,我们肯定是继续对连通块 \(L\) 按权值从小到大依次加边,直至出现环或分叉为止。对于环,可以在跑 Kruskal 时用并查集判,发现就在对于连通块上的结点挂着;对于度数只要开个数组记一下,打个标记就行。最后一遍 Dfs 处理出最近产生非链连通块的祖先。

复杂度 \(O((N+Q)\log N+M\log M)\),瓶颈 LCA 和排序。

参考实现:https://loj.ac/s/1127839

C - Fun Tour

挺神仙的交互 + 构造。

首先,用 \(O(N)\) 次询问获取完整的树形态是比较困难的,这说明我们构造一组解不一定依赖完整的树结构。

不过我们还是考虑一下给定了树怎么做。非常重要的一点:度数不超过 \(3\)。若是我们随意定一个根,那么可以每次选一个深度最大的点,满足与上一次选择的 LCA 为根,也就是说不在根同一个儿子的子树内。可以保证这样的方案必然距离不增。但这就要求根的各个子树尽可能均匀,而这和重心的概念与性质十分吻合。

那么选一个重心作为根,那么根的度数为 \(2\)\(3\)。稍微讨论一下:

  • 根有两个儿子:由于以重心为根的子树大小不超过一半,那么两棵子树的大小差显然不超过 \(1\),直接轮流取必然存在合法解。
  • 根有三个儿子:若三个子树大小为 \(a,b,c\),不失一般性设 \(a\ge b\ge c\)。根据重心的性质有 \(a\le b+c+1\)。思考按这样的方式不断操作,由于 \(b+c\) 减小的次数不小于 \(a\),那么最终会有 \(a=b+c+1\) 的局面出现。这时候不妨合并 \(b,c\),从而归约到两个儿子的情况。注意一个 corner case,就是当前刚刚选了 \(b\) 然后 \(a=b+c+1\),但是下一个最大的应该在 \(c\) 中,那应该在手动操作一次 ,否则可能会出现不合法的结果。

最后就是通过不超过 \(4N\) 次询问,处理出:

  • 树的重心;
  • 以重心为根每个点的深度;
  • 每个点分别属于重心的那个子树。

前两者不难得到,其中重心可以先任意定根,然后求出每个子树的大小,最后子树大小 \(\ge \left\lceil\frac{n}{2}\right\rceil\) 中大小最小的即为重心。于是前两个要素需要 \(2N\) 次询问。对于最后一个,很显然如果 \(\text{dep}_x + \text{dist(x,y)}=\text{dep}_y\)\(y\) 就是 \(x\) 的后代。考虑到度数不超过 \(3\),那只要询问两次距离(第三个可以排除前两个)就行了。最后总询问次数不超过 \(4N\)。复杂度 \(O(N\log N)\)

参考实现:https://loj.ac/s/1128474

posted @ 2021-04-30 16:07  -Wallace-  阅读(317)  评论(0编辑  收藏  举报