ZLOJ练习28总结

written on 2022-06-29

这场比赛打的不好,但是也有一些收获。

\(A\) 题相对比较简单,因为是考虑对于每一个根统计答案,排除贪心的思路后,就可以每一次换相邻的根统计贡献计算答案了。链接

\(B\) 题其实也是很明显的,读完题后很快就有两种可能的思路:树形dp 或者是贪心。然后仔细观察数据范围,很明显应该要设计一个 \(O(n)\) 的做法嘛,因此考虑贪心,\(2e6\) 的数据或许可以带点小常数,于是从贪心的角度,思考本题。

做这种贪心题,应该要联想到之前做过的一道贪心题,Warehouse。这两道题的相似之处在于,每一次操作,或者说每一个位置,贡献都是一。因此,在贡献一定的情况下,优先考虑花费较小的位置。但是这题的难点其实主要在于,发现自底向上贪心的正确性,这里简单的说一下。

考虑 \(i\) 有一个儿子 \(j\)\(j\) 有一个儿子 \(p\),那么假如删了 \(p\),对 \(j\) 产生影响,可能导致 \(j\) 不能删除。但是这对于更上层的祖先节点并没有影响,删 \(j\) 或是删 \(p\),贡献均为 \(1\),而且对其他节点的影响也是相同的,至此我们证明了自底向上删除节点的正确性。

代码实现较为简单。兔子与樱花.

\(C\) 题事实上也是一道很有价值的题目,HOT-Hotels. 一开始写这题有很多的思路,但是正确性都是有问题的。

先说一下做题过程中的细节问题,如果碰到要统计一棵子树内某深度的节点有多少个,正确而易于实现的方法是:

now=cnt[dep];
for(int i=head[x];i;i=nxt[i]) dfs(...);
ANS=cnt[dep]-now;

这题是弱化版,数据范围较松。介绍一下补题时采用的方法,固定三个点中的一个点为根节点,假设当前递归到节点 \(x\),深度为 \(dep\),那么只需要再统计 \(x\) 这棵子树内,深度为 \(2dep\) 的节点个数即可。算法看似正确,但是实则:

对于节点 \(x\) 而言,考虑其儿子 \(son1\)\(son2\),那么这两棵小子树内的节点内部之间,是不满足 其中任意两点的距离相同 这一条件的,可以画图理解。因此,考虑容斥,总的照旧计算,但是减去每一棵子树内的那些内部点(不满足条件的)。具体代码在链接中可看。

\(D\)魔兽地图还没补,暂且搁着。

update on 2022-7-31

对于 \(C\) 题,其实博文中介绍的方法可以加以总结:为了统计子树信息,可以开一个桶,在递归子树之前记录其值为 \(now\),然后用递归后的桶信息减去 \(now\) 即为子树的信息了。这个方法在之后 \(7\) 月份的一篇文章里也会有提到。

posted @ 2022-07-31 22:00  Freshair_qprt  阅读(36)  评论(0编辑  收藏  举报