某个图函数的题

一开始给一个数组 \(a_1, a_2, \cdots, a_n\) 。每次变换所有 \(a_i\) 会变成 \(a_i\) 出现的次数。询问 \(k\) 次变换后,\(a_1,a_2,\cdots,a_n\) 是啥。

这里 \(a_i\) 本身是不关键的,可以当成颜色看待。我们先让所有 \(a_i\) 进行第一次变换,那么 \(1 \leq a_i \leq n\)。然后让 \(k\) 减少 \(1\)
第一次变换可以暴力地 \(O(n)\) 解决。这个一个好处让 \(1 \sim n\) 的范围方便建树。

然后考虑接下来的变换。

注意每次变换,可以当成一个映射 \(f : a_i \rightarrow c(a_i)\)\(c(a_i)\)\(a_i\) 当前的出现次数。显然在规则的函数映射下,对他们的每次变换连边,至少形成一些基环树。存在环是显然的。

我们只需要暴力 \(n\) 次,就可以扣出所有基环树,找到每个 \(a_i\) 所在的树,和这棵树的环长。这个暴力的时间复杂度是 \(O(n^{2})\) 的。

对于每棵树,他的环长 \(r<n\) ,我们可以让 \(k\) 超出 \(n\) 的部分模掉 \(r\) 。剩下的点暴力在树上跑即可,时间是 \(O(n^{2})\) 的。当然可以在基环树上倍增,时间是 \(O(n \log n)\) 的。但是瓶颈在于抠树。

实际上还有另一种理解方式。不从函数映射的角度考虑,发现问题本质上是一种颜色合并。那么我们可以用启发式合并连边。总之边数是 \(O(n)\) 条的,连边的时候不是瓶颈。合并的时间均摊是 \(O(n \log n)\) 的。这样连边并且抠出基环树的时间复杂度就是 \(O(n \log n)\) 了。

posted @ 2025-05-06 11:35  03Goose  阅读(6)  评论(0)    收藏  举报