• 关于树上差分


    关于树上差分,可参见网友一博客

    https://www.luogu.com.cn/blog/sincereactor/shu-shang-ci-fen-di-liang-zhong-sai-lu

    这里我也来说两句:

    树上差分分为两个(就像树上dp一样)

    1.点差分

    2.边差分

    1.点差分:
    二.关于点的差分(如将路径上的所有点权值加一,求最后点的权值)

    此操作中我们这样维护:每次经过一条边,(如从u到v)我们让tmp[u]++,tmp[v]++,tmp[LCA(u,v)]--,tmp[grand[LCA(u,v)][0]]--。(最后要把tmp推上去)

    以一次添加为例想象一下,首先u到根的路径上tmp都+1,此时u到根间结点tmp都为1,之后v到根路径上tmp+1,此时u到LCA前一个,v到LCA前一个点的tmp都+1,而

    LCA到根的所有点都+2,然后从tmp[LCA]--,更新上去,此时u-v路上所有tmp都+1,已经达到目的。

    而多余的是什么部分呢,也就是LCA的上一个结点(grand[LCA][0])到根的这一段都多加了1,所以tmp[grand[LCA][0]]--,更新上去,也就完成了。

    实际操作时也不需要每次更新都推上去,只要把四个tmp维护好,最后Dfs走一边就更新完了。

    如图

    关于边差分:

    一.关于边的差分(如找被所有路径共同覆盖的边)

    首先我们除了一般的grand,depth等数组以外,多开两个数组:tmp和prev。

    tmp用来记录点的出现次数(具体点说实际上记录的是点到其父亲的边的出现次数),prev记录每个点到其父亲的那条边。对于一条起点s,终点t的路径。我们这样处理:

    tmp[s]++,tmp[t]++,tmp[LCA(s,t)]-=2。(记住:最后要从所有叶结点把权值向上累加。)以一次操作为例,我们来看看效果(可以画一张图)。首先

    tmp[s]++,一直推上去到根,这时候s到root的路径访问次数都+1,tmp[t]++后,t到lca路径加了1,s到lca路径加了1,而lca到根的路径加了2。

    这时,我们只需要tmp[LCA(s,t)]-=2,推到根,就能把那些多余的路径减掉,达到想要的目的。而这是一次操作,对于很多次操作的话,我们只需要维护tmp,而不

    必每次更新到根,维护好tmp最后Dfs一遍即可。这时如果tmp[i]==次数的话,说明i到其父亲的边是被所有路径覆盖的。如图

    https://cdn.luogu.com.cn/upload/pic/20327.png

    谢谢

  • 相关阅读:
    10-3 集合之Set
    【Angular】排序
    【Mongous】
    【验证码】
    爬虫
    【DOM】
    年月日
    【Mocha】
    【Test】
    洛谷——P1823 音乐会的等待
  • 原文地址:https://www.cnblogs.com/starseven/p/11958184.html
Copyright © 2020-2023  润新知