1 条题解

  • 0
    @ 2025-10-22 17:08:10

    题意理解

    我们有一个 n×mn \times m 的网格图(经纬度),每个点是一个国家,边是道路:

    • 横向边(i,j)(i,j)(i,j+1)(i,j+1) 相连,并且第 mm 列与第 11 列相连(环形)
    • 纵向边(i,j)(i,j)(i+1,j)(i+1,j) 相连(但 nn11 不相连)

    每条边有一个安保代价(权重)。

    每个询问 [li,ri][l_i, r_i] 表示:经度在 [li,ri][l_i, r_i] 之间的国家处于战争,不能使用。我们要在剩下的和平国家之间,选择一些和平道路(两端都是和平国家),使得和平国家连通,并且总安保代价最小。


    核心难点

    1. 图非常大mm 最多 10910^9(测试点4),nn 最多 100100,不能直接存储整个图。
    2. 环形结构:横向是环,战争区间会破坏环的连续性。
    3. 多次询问:需要高效处理每个询问。
    4. 边权随机生成:不能依赖特殊权重结构。

    解题思路

    关键观察

    和平国家 = 所有国家去掉 [li,ri][l_i, r_i] 列。
    由于 nn 较小(≤100),我们可以把地图看作 nnmm 列的网格,按列处理。


    问题转化

    删除 [li,ri][l_i, r_i] 列后,剩下的是前后两个连续区间的列(因为环形,删除一段连续区间后,剩下的是两段连续区间)。

    设删除区间 [l,r][l, r],那么和平区域是:

    • 左段:列 [1,l1][1, l-1]
    • 右段:列 [r+1,m][r+1, m]

    我们要在这些列对应的点上求 MST。


    预处理列区间MST信息

    由于 nn 很小,我们可以预处理每个列区间的 MST 相关信息。

    定义 L[i]L[i] 表示从第 11 列到第 ii 列这些列的 MST 信息(不仅仅是权重和,还要记录与右边界相连的边信息,因为合并区间时需要)。

    同样定义 R[i]R[i] 表示从第 ii 列到第 mm 列这些列的 MST 信息。


    合并两个区间

    对于询问 [l,r][l, r],和平区域是左段 [1,l1][1, l-1] 和右段 [r+1,m][r+1, m]

    我们已知:

    • L[l1]L[l-1] 包含列 1..l11..l-1 的 MST 信息
    • R[r+1]R[r+1] 包含列 r+1..mr+1..m 的 MST 信息

    现在要把这两个区间合并成一个连通图(因为左右两段在环上是相邻的,它们之间在第 11 列与第 mm 列有横向边连接)。


    区间MST信息的表示

    我们不可能存整个 MST(太大),但可以存:

    • 该区间的 MST 权重和
    • 该区间最左列的每个节点在 MST 中的连通分量编号
    • 该区间最右列的每个节点在 MST 中的连通分量编号
    • 以及这些连通分量之间的边(用于合并时)

    实际上,由于 nn 很小,我们可以用最小生成树的关键边思想:当合并两个区间时,只需要考虑两个区间相邻边界列之间的横向边,以及两个区间各自内部的连通情况。


    做法:Kruskal 重构树 / 并查集合并

    我们可以预处理:

    1. 对每个前缀 [1,i][1,i] 计算 MST,并记录:

      • 总权值 sumL[i]sumL[i]
      • 最右列(第 ii 列)的 nn 个节点在 MST 中的连通块编号(映射到 1..n1..n
      • 这些连通块之间的最小边权(用于与右区间合并时)
    2. 对每个后缀 [i,m][i,m] 类似处理,得到 sumR[i]sumR[i] 和最左列连通信息。

    3. 对于询问 [l,r][l,r]

      • 左区间 [1,l1][1,l-1] 的 MST 权值和 = sumL[l1]sumL[l-1]
      • 右区间 [r+1,m][r+1,m] 的 MST 权值和 = sumR[r+1]sumR[r+1]
      • 但直接相加会重复计算一些边(因为左右两段在列 1 与列 m 处有环边连接),需要合并。

    合并左右区间

    左右区间合并时,新增的边是:

    • l1l-1 列与第 ll 列之间的横向边(但第 ll 列是战争列,不能用)
    • 实际上,左右区间在环上相邻的边是:第 11 列与第 mm 列之间的横向边(因为环形)

    所以合并时,我们加入第 11 列与第 mm 列之间的 nn 条横向边,用 Kruskal 方法合并左右区间的连通块。


    实现方法

    我们预处理:

    • pre[i]pre[i]:列 [1..i][1..i] 的 MST 信息(权和 + 右边界连通性)
    • suf[i]suf[i]:列 [i..m][i..m] 的 MST 信息(权和 + 左边界连通性)

    对每个询问:

    1. pre[l1]pre[l-1]suf[r+1]suf[r+1]
    2. 将它们的 MST 权和相加
    3. 加入第 11 列与第 mm 列之间的 nn 条边(边权由输入生成器确定)
    4. 在这些边 + 左右区间边界信息上做 Kruskal,得到合并后的 MST 权和

    复杂度

    • 预处理 O(nmlogn)O(n m \log n)mm 大时不能直接做,需要优化)
    • 每个询问 O(nlogn)O(n \log n) 合并

    对于 mm 很大的情况,不能真的预处理每个前缀/后缀,需要用线段树维护区间 MST 信息,支持区间合并。


    关键数据结构

    我们可以用线段树,每个节点 [l,r][l,r] 存储:

    • 该区间的 MST 权和
    • 左边界列(第 ll 列)的连通信息
    • 右边界列(第 rr 列)的连通信息

    合并两个相邻区间时,只需在中间加入两区间相邻列之间的 nn 条横向边,做一次 Kruskal。

    这样预处理 O(mnlognlogm)O(m n \log n \log m),查询 O(nlogn)O(n \log n)


    总结

    这道题的核心是:

    1. 将环形区间删除转化为两个连续区间的合并
    2. 利用 nn 小的特点,用边界列的连通性表示区间 MST 信息
    3. 用线段树维护区间 MST,支持快速合并
    4. 询问时合并左右两段,并加入环形连接边,求最终 MST

    这样就能在 nnmm 大的情况下高效处理多次询问。

    • 1

    信息

    ID
    3514
    时间
    2000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者