灾后重建题解

因为某大学需要,被教练抓(动词不对不要管)去思考这道题,于是一个晚修报销

首先有一个显然的结论:每个询问的答案一定在最小生成树上。
接着,我们定一个常数c,对于每个询问的k进行分类:

1、k>c,此时我们暴力解决该询问,即对于该询问的所有特殊点进行暴力,两两之间求lca然后询问路径上的最值。
树路径的最值询问可以使用树链剖分,时间复杂度一次询问o(log^2 n)
然而这题并没有修改操作,树链剖分不划算。
我们改用倍增算法,设f[i,j]表示结点i到其2^j级祖先的树路径的最值。
预处理o(n log n),一次询问需要求lca所以要o(log n)。用tarjan求lca可以做到单次询问o(1)(注意这里把并查集的复杂度当作o(1))。

2、k<=c,此时我们每一次解决k值相同的所有询问。
即,我们枚举k,然后枚举c,然后解决所有要求模k余c的点为特殊点的询问。
我们按照升序添加所有符合模k余c的点,线段树维护区间最值,其中叶子结点的值也相当于询问树路径上的最值。
那么每个询问都对于一个区间查询,用线段树做每次插入/删除复杂度为o(log n)。

我们取c=根号n,那么第一类复杂度为o(n*根号n*log n),第二类复杂度也为o(n*根号n*log n)。(这里的复杂度分析没有考虑n,q的区别,因为他们同规模这里不予区分)
因为c大则特殊点数目小,c小则k值不同取值小。

你可能感兴趣的:(灾后重建题解)