记一类分治思想

这种分治思想大概是我在一年前看到的,但当时只看到了一道能用的题,就并没有当回事,最近又见到了可以用的题目,来写个随笔记一下。

不太清楚这个叫啥分治,要是有人在看而且知道可以跟我讲一下。

时间线段树(线段树分治)与这一思想较为类似,可以去看我的 时间线段树(线段树分治)学习笔记

问题一:给定一个 nm 边有向图,对于所有 1u,v,wn,求 uv 且不经过 w 的最短路长度之和。

这是我最早见到的这个思想的题目,虽然没找到题在哪里。

容易发现暴力 Floyd 一遍是 O(n4) 的,能不能想一个更快的算法呢?是有的。

考虑 Floyd 算法的最一般形式的由来,设 dpS,u,v 表示 uv 只能经过 S 集合中的点的最短路,有转移方程:

dpS{w},u,v=min{dpS,u,v,dpS,u,w+dpS,w,v}

然后按顺序将节点加入 S 之后滚掉 S 这一维就是 Floyd 算法。

注意到节点加入 S 的顺序其实是不重要的,发现在刚刚的 O(n4) 流程中没有充分利用这一点,进行了很多重复计算。考虑这样一种分治算法:

FLOYD(int[][]& dp, int l, int r) # 在 dp 数组的基础上,再添加 [l, r] 的点到点集 S 中
    for k in [l, r] do
        for i in [1, n] do
            for j in [1, n] do
                dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])

DIVIDE_AND_CONQUER(int[][] dp, int l, int r) # 计算不加入 [l, r] 范围的点的全源最短路
    result = 0
    if l == r do
        for u in [1, n] do
            for v in [1, n] do
                result += dp[u][v]
    else do
        mid = (l + r) / 2
        dp_new = dp
        FLOYD(dp_new, mid + 1, r)
        result += DIVIDE_AND_CONQUER(dp_new, l, mid)
        dp_new = dp
        FLOYD(dp_new, l, mid)
        result += DIVIDE_AND_CONQUER(dp_new, mid + 1, r)
    return result

这种算法的正确性显然,时间复杂度可以写作 T(n)=2T(n2)+O(nN2),用主定理可知为 O(N3logN)

观察以上过程,可以简单地总结一下这类分治算法的流程:

  • DIVIDE_AND_CONQUER(l, r):要求解 [l,r] 范围的答案。
  • 如果 l=r,对这个点求解即可。
  • 否则取中点 mid 进行分治:
    • 添加右半边对左半边的贡献,递归左半边统计答案。
    • 将右半边的贡献擦除,添加左半边对右半边的贡献,递归右半边统计答案。
    • 如果需要,将两部分答案合并。

总结:这类分治算法通过求解多个点的答案时共用信息的方式,大大减少了计算量,通常可以把一个暴力计算的 O(n) 降低到 O(polylogn)

问题二(CF1681F):有一棵 n 个点的树,每条边有颜色,对于每条路径 uv,求路径上恰好出现一次的颜色数量的和。

本题有一个 O(n) 做法,是类似虚树的思想,对每个颜色分开统计答案,但这不在我们讨论的范畴。

我是从 tourist 大神的 代码 里再次看到的这个思想。

不难发现,对于颜色 c 的答案即为把所有颜色 c 的边删掉后,每条 c 边连接的两个连通块大小之积的和。

接着利用上面的思想,DIVIDE_AND_CONQUER(l, r) 即为要求解 c[l,r] 范围的答案。

使用可撤销并查集维护连通块,对于分治中心 mid,我们把右半边的边连接的连通块合并,然后统计左半边答案,之后执行撤销操作,把左半边的边连接的连通块合并,然后统计右半边答案。对于单点的求解,枚举颜色 c 的边,求两个连通块大小之积即可。

时间复杂度为 O(nlog2n)

问题三(P4141):背包,所有少一个物品的情况的最大价值之和。

O(nm) 做法,不过由上面的分治,可以有 O(nmlogn) 做法。

其他应用:“线段树分治”(时间轴线段树)的思想比较类似,只是统计贡献的方式略有不同。

问题四(ABC279E

posted @   rui_er  阅读(324)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示