zoukankan      html  css  js  c++  java
  • 「笔记」长链剖分

    树有很多种剖分。
    常见的是重链剖分。
    然而还有针对树深度信息维护的长链剖分。
    和重链剖分类似。
    长链剖分维护长链,同时也有长儿子和短儿子。
    所有长链长度之和为(n),这个显而易见。
    那么我们在维护和长度相关的信息的时候。
    一般情况下是将儿子的长度位移,这样的话可以直接用指针数组继承长儿子的信息。
    同时暴力统计短儿子的信息。
    这样每条长链最多被扫一次。
    复杂度就是完美的(O(n))

    T1.(Hotel)加强版
    我们设(f[x][i])为距离(x)的长度为(i)的点的个数,(g[x][i])为有两个点在(i)的子树中,且其到达他们的(LCA)的距离为(d),他们的(LCA)距离(x)的长度为(d-i)的点对个数。
    那么有:

    [ans+=g[x][0]+g[x][i]*f[t][i-1]+f[x][i]*g[t][i+1],f[x][i]+=f[t][i+1],g[x][i]+=g[t][i-1] ]

    然后这个东西直接做复杂度是(O(n^2))的。
    考虑用长链剖分优化。
    我们发现后面的转移其实都是一个位移。
    我们用指针实现对长儿子的(shift),然后短儿子就暴力扫短儿子内部的最大深度。
    这样每个长链就被扫一次,复杂度就是(O(n))的。

    T2.谈笑风生
    我们发现其实只需要关注(a,b)的情况。
    1.(a)在上(b)在下,这个时候统计距离(a)的长度小于(k)(b)(sz_b-1)的和就可以了。
    2.(b)在上(a)在下,这个时候统计(a)的满足限制的祖先个数即可。
    第二个很简单。
    考虑第一个用长剖维护。
    (dp[i][j])为距离点(i)的长度为(j)(sz_b)和。
    那么前缀和不好维护,维护一个后缀和就可以(O(n))(dp)了。

  • 相关阅读:
    C#的list和arry相互转化
    c++11の的左值、右值以及move,foward
    c++11の异步方法 及线程间通信
    C#的static
    HDU4027 Can you answer these queries?
    POJ3264 Balances Lineup
    ZOJ1610 Count the Colors
    ZOJ4110 Strings in the Pocket(2019浙江省赛)
    HDU1698 Just a Hook
    POJ3468 A Simple Problem with Integers
  • 原文地址:https://www.cnblogs.com/Lrefrain/p/12346367.html
Copyright © 2011-2022 走看看