模板——长链剖分

长链剖分

做法

类似于轻重链剖分,只是将轻重链剖分中重儿子的定义改为,子树中深度最大的儿子

那么可以通过长链剖分来维护有关深度的信息

考虑维护节点$x$的深度信息

那么先让节点$x$继承重儿子的所有信息

再暴力合并所有轻儿子的信息

代码跟轻重链剖分差不多

void dfs(int x,int fa)
{
    md[x]=de[x];
    for (int i=0;i<(int)e[x].size();i++)
    {
        int u=e[x][i];
        if (u!=fa)
        {
            de[u]=de[x]+1;
            dfs(u,x);
            if (md[son[x]]<md[u])
            {
                son[x]=u;
                md[x]=md[u];
            }
        }
    }
}

复杂度&证明

节点x继承重儿子信息的复杂度可以做到$O(1)$

那么整个长链剖分的复杂度为$O(n)$

证明:

因为每一个节点都属于树上的一个重链上

而每个重链作为轻儿子去暴力合并只有一次,就是当在重链顶端的节点的父亲合并时,将这条重链视为轻儿子

那么每个点被枚举到1次

那么均摊复杂度为$O(n)$

 

原文地址:https://www.cnblogs.com/huangchenyan/p/11844824.html