zoukankan      html  css  js  c++  java
  • 树上差分的两种实现形式

    简单理解树上差分(点,边)

    关于树上差分,我在这推荐一道题目POJ 3417 。

    题目翻译:https://loj.ac/problem/10131。

    树上差分用来解决点的覆盖或者边的覆盖的问题,需分别运用点的差分或者边的差分。

    先从例题入手:

    给定点数为N,边数为N-1的树(无向边且无重边),先有M条连接a,b的非树边,求每条“树边”被“非树边”覆盖了多少次?

    边的差分:

    先设一个F【x】,是一个差分数组,表示从X到X的父亲的边被覆盖的次数。对于每一次输入的a , b,朴素算法是O(n)的去遍历每一条边,这样的时间复杂度太高了,我们就可以用差分的思想去优化,就是树上差分,即F[a]++,F[b]++,F[lca(a,b)]-=2;

    从X到X的父亲的边被覆盖的次数就是X的子树和了,前缀和的思想。

    但是我无法证明这种方法,如果有神犇能证明,麻烦下方评论告知,O(∩_∩)O谢谢。

    再来一道例题:

    给定点数为N,边数为N-1的树(无向边且无重边),先有M条连接a,b的非树边,求每个“点”被“非树边”覆盖了多少次?

    不难看出,这道题只是把“树边”改成了“点”。

    点的差分:

    设F【x】为x被覆盖的次数。修改F【X】的时候也要变化,还是输入a,b。修改的操作为F[a]++,F[b]++,F[lca(a,b)]--,F[father[lca(a,b)][0]]--;最后一个是LCA(a,b)的父亲。同样,X的子树和就是X点被覆盖的次数。求每个点的子树和只需要DFS一次,复杂度是O(NlogN)的。

    实在不理解可以举2个例子模拟一下:

    1.从a到b。a,b均不是LCA(a,b)。

    2.从a到b。a,b其中之一为LCA(a,b)。

    总结一下:树上差分用来解决“点的覆盖”或者“边的覆盖”的问题,是朴素的直接遍历算法的优化,将朴素算法覆盖的时间复杂度O(N*M),直接优化为O(N),时间复杂度十分优秀。

  • 相关阅读:
    Android Studio的git功能的使用介绍
    如何用Android Studio同时使用SVN和Git管理项目
    【.NET深呼吸】动态类型(扩充篇)
    【.net深呼吸】动态类型(高级篇)
    【.net深呼吸】动态类型(娱乐篇)
    VS 2015相当不错的功能:C#交互窗口
    计算照片的面积(WPF篇)
    计算照片的面积(UWP篇)
    【Win 10应用开发】把文件嵌入到XML文档
    【.NET深呼吸】基础:自定义类型转换
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9498276.html
Copyright © 2011-2022 走看看