动态开点线段树 + 可删堆.
首先由于边权都是 $>0$ 的,易知答案一定是最小生成树上的一条边,用反证法不难证明.
先做出一棵最小生成树,并钦定一个点为根,对每个点 $x$ 维护一个 ${\rm res}(x)$ ,表示 $x$ 的所有异色儿子与 $x$ 的最短距离,没有异色儿子则视为 $\inf$ ,那么答案就是 $\min_x \lbrace{\rm res}(x)\rbrace$ .
每次修改 $x$ 的颜色时,会影响到 ${\rm res}(x),{\rm res}(fa(x))$ ,我们用一个可删小根堆维护所有的 ${\rm res}(x)$ ,修改时将 ${\rm res}(x),{\rm res}(fa(x))$ 从堆中删掉,计算出新的 ${\rm res}(x),{\rm res}(fa(x))$ 后再将它们加入到堆中,查询堆顶即为答案.
对每个 $x$ 开一棵以颜色为下标的线段树,为每个叶子节点开一个可删小根堆,对于 $x$ 的每个儿子 $y$ ,将 $(x,y)$ 的边权加入到 $col(y)$ 对应的堆中,计算 ${\rm res}(x)$ 时只需查询 $[1,col(x)),(col(x),K]$ 这两个区间内叶子节点堆顶的最小值.
修改 $x$ 的颜色时需要对 $fa(x)$的线段树修改,将原来颜色的贡献删掉,将新的颜色的贡献加入.
叶子节点不会超过 $n+q$ 个,可删堆就只需要开这么多个,如果开 $O((n+q)\log (n+q))$ 个可能会 RE 或 CE.
时间复杂度 $O(m\log m+(n+q)\log (n+q))$ .
1 | //%std |