Files
python/TangDou/AcWing/P4556.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

1.5 KiB
Raw Permalink Blame History

一、朴素思想

要想求出每个点存放最多的是哪种类型的物品,需要求出每个点上存放的每种物品的数量。

朴素做法,对物品的类型进行离散化(最多 M 种不同物品),然后对每个点 x 建立一个计数数组 $c[x][1$~$M]$。 依次执行每个发放操作,对 xy 的路径上的每个点 $p$ c[p][z]++ ,最终扫描计数数组得到答案。 因为路径上每个点都需要执行一次$++$操作,但是这样肯定超时,因此需要优化。

二、树上差分优化

为了避免遍历从 xy 的路径,我们可以使用树上差分,对于每条从 xy 的路径上发放 $z$,使 $c[x][z] + 1$,使 $c[y][z] + 1$,由于路径上所有点都 $+ 1$,包括 x 和 $y$的最近公共祖先,因此需要使 $c[lca(x, y)][z] - 1$,使 $c[father(lca(x, y))][z] - 1$。

三、线段树+线段树合并优化

为了节省空间快速使两个计数数组相加,可以使用线段树合并:

  • 对于每个点建立一个动态开点的线段树,来 代替差分数组,动态的维护最大值以及最大值对应的类型,然后深搜求子树和,每次的求和等价于每两个线段树合并,最终得出每个点的答案。

四、关于离散化

看题解有的网友说$z$的范围是1e9,需要开离散化,所以代码中都有离散化的部分。 但看了下无论是洛谷还是AcWing,现在的数据上限都是1e5,开不开离散化都行。