P4197 Peaks [克鲁斯卡尔重构树 + 主席树]
部分kruskal重构树内容摘抄于 bzt神仙的blog Problem 在 \(Bytemountains\) 有 \(n\) 座山峰,每座山峰有他的高度 \(h_i\) 。有些山峰之间有双向道路相连,共 \(M\) 条路径,每条路径有一个困难值,这个值越大表示越难走,现在有 \(Q\) 组询问,每组询问询问从点 \(v\) 开始只经过困难值小于等于 \(x\) 的路径所能到达的山峰中第 \(k\) 高的山峰,如果无解输出 \(-1\) 。 kruskal重构树是用来解决一些诸如“查询从某个点开始 经过边权不超过 \(val\) 所能到达的节点”的问题 所以很显然 在最小生成树上是最优的。。其他多余的边可以不需要考虑。。 那我们在跑kruskal的时候重新建边。。 克鲁斯卡尔重构树的思想就是在建最小生成树的时候不是直接连边 而是新建一个节点 并把这个节点的值设为边权 然后令两个连通块的代表点分别作为它的左右儿子 然后令这个新节点成为整个连通块的代表点 即如果 \(u\) \(v\) 不连通 sort(q + 1 , q + m + 1 , cmp) ; for( int i = 1 ; i <= n ; i ++ ) fa[i] = i ; tot = n ; for( int i = 1 ; i <= m ; i ++ ) { int u = find(q[i].u) , v