ZLOJ练习40总结

written on 2022-07-13

写一点随记:

  1. 对于一张有向图,如何判环?

答:直接跑拓扑排序,将某一点加入队列的条件是这一点的入度为 \(0\),最后查看是否有点的入度不为 \(0\)。时间复杂度 \(O(n)\),代码实现也不难。

  1. 对于树上点权相乘有关的题目,可以考虑特殊情况,因为乘法的速度很快,可以考虑证明只有较小的某些值(如 \(1,2\))参与了乘法的累计。

  2. \(\text{MLE}\) 的另一种可能原因是递归爆栈。

就这三点,然后具体看题目。

第三题太愚蠢,不写了。

第四题题目看错了,不写了。

第五题思路奇特,不写了。

好的先看第五题

这题考场上的时间不是很够,匆匆敲了个骗分代码就交了。事实上这题的关键在于发现题目的数据范围。发现 \(n\leq 16\),那么很显然就有爆搜和状压两种思路。

但是没有很明显的思路,于是考虑先模拟一些情况。经过一些操作,我们发现:因为字符串顺序可更改,所以随便画一些点,就能够发现,对于几个字符串,它们构成的最小个数,也就是:

“对于每一个字母在每一个单词中出现的次数的 \(\min\) 加上 每一个字母在每一个单词中出现的次数减去这个 \(\min\)。”

有点绕,可以手动模拟感性理解一下。

然后给出一组样例:

4

abca

abc

ade

adf

然后根据这样的样例,就可以发现这样的思路是错的。

为什么呢?因为合并应当是有序的。也就是说这组样例中的 \(1,2\)/\(3,4\) 两串应当优先合并,因为他们的相同前缀更长。所以在状态转移时,就不是一个一个地加点,而是由子集转移而来!

至此我们已经有了基本的思路,现在的目标与思路就很明确了。原题即转化为将给定的字符串分成若干组,然后合并成新的组,最后求全集。接着就是转移的问题了,对于一个二进制状态,它的重组最长公共前缀是一定的,可以提前预处理好(代码中即为 \(sum\)),那么转移时,为了保证最优,肯定是用原先的两个答案相加,再减去这个前缀,答案可能偏大,因此转移时从每一个子集转移而来,这样就能够保证获得最优解。

代码在链接中。

第四题本来是一道很有价值的贪心转化题,但是题目看错了,导致前面的思考均为废谈,因此在这里就简单地说一下思路。

贪心的思路是很明确的,要考虑的问题就是对于环上的操作,贪心的正确性。一般来说,确定一个起点,在顺序扫描的时候顺便加入所有新的精灵值到 \(\texttt{multiset}\) 中,然后贪心的策略就很明显了。但是为了保证贪心的正确性,要是对于某一个矮人的分析中,选取的精灵是从后面的环绕回来的呢?那就有后效性了,因此本题的关键在于找到无后效性的起点。

就讲这么多,剩下的可以先自己思考一下,推出式子(这也不难),然后就可写了。

第三题可以参考一下其他的题解,剩下的就不再赘述了。

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