• 学习笔记 启发式合并


    启发式合并

    前言

    启发式合并十分得神奇,如果不刻意去想可能几乎想不到这种优化方法,但是在某些时刻看似是暴力的代码套上这几个字再加上证明复杂度,就能缩一圈,但没有模板,代码因题而异,十分灵活。

    概念简述

    • 对于 (n) 个初始大小为1的可重集,每次选择(被动)两个集合合并时,每次将 (S_1)(S_2) 合并的代价是其中一个集合的大小,而目的时合并成 (1) 个可重集的最小代价。

      每次合并,很显然的一种贪心方法是将较小的集合合并到较大的集合,复杂度为 (O(min(S_1,S_2))) ,而最后的时间复杂度的阶也很神奇,是 (O(nlog_2n))

    证明

    观察每次合并操作将较小的集合合并到较大的集合,而每个元素只有在较小的集合才会产生贡献,但每次合并操作对于较小的集合都会扩大一倍,而对于刚开始的大小为 (1) 的集合,最多会带此元素作为较小的集合扩大 (lfloorlog_2n floor) 次,而每个元素扩大 (lfloorlog_2n floor) 次后复杂度为 (O(nlog_2n)) ,对于随机数据完全达不到这个上限,我们还是保守的将其估计为此。

    例题

    (持续更新ing)

    • (large exttt{LG U41492})

      树上启发式合并模板题。

      将问题转换到了树上,其实就是规定了每次操作合并的两个可重集。

      在 DFS 遍历到某个节点的时候保留一颗最大的子树的答案,再将其它兄弟子树所有节点后合并到那颗最大的子树的答案中,得到父亲节点的答案。

      在一个节点中,每次对于要合并的子树大小最少扩大一倍,而对于某个节点,它在较小的子树中合并产生贡献为包括它的所有子树的合并次数,而这个合并次数不超过 (log_2n) ,因此合并次数也是不超过 (O(nlog_2n)) (对于随机数据十分得松)。

  • 相关阅读:
    伺服电机常见故障分析汇总
    PLC常见四大故障及其处理方法
    Qt QString的arg()方法的使用
    Qt 线程池QThreadPool类、QRunnable类
    C++线程池的实现
    C++ List的用法
    C++语言堆栈的详细讲解
    QT中的QQueue类、C++中的queue类
    Qt platform plugin 'windows' 问题的解决方法
    电气接地的相关介绍
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/14518380.html
Copyright © 2020-2023  润新知