• 【树】树上启发式合并


    树上启发式合并

    学习资料:OI Wiki 树上启发式合并

    时间复杂度:(mathcal{O}(nlogn))

    作用:

    树上启发式合并 在计算的时候,保留重儿子的子树答案,清除轻儿子子树的带来更新,再将当前树的所有轻儿子影响的更新重新计算合并到重儿子的更新上。用于计算所有子树的答案。

    模板:

    vector<int>p[maxn];
    int siz[maxn],son[maxn],fa[maxn];
    void dfs1(int u,int f)
    {
        siz[u]=1;son[u]=0;fa[u]=f;
        for(int i=0;i<p[u].size();i++)
        {
            if(p[u][i]==f)continue;
            dfs1(p[u][i],u);
            siz[u]+=siz[p[u][i]];
            if(siz[p[u][i]]>siz[son[u]])son[u]=p[u][i];
        }
    }
    void merge(int u,int v)//v是最外层树的那个重儿子
    {
        /*
        记录u节点对答案的更新
        */
        for(int i=0;i<p[u].size();i++)
            if(p[u][i]!=fa[u]&&p[u][i]!=v)
                merge(p[u][i],v);
    }
    void clear(int u)
    {
        /*
        撤销u节点的更新
        */
        for(int i=0;i<p[u].size();i++)
            if(p[u][i]!=fa[u])clear(p[u][i]);
    }
    void cal(u)
    {
        ;
    }
    void dfs2(int u,bool is)//is=1表示当前子树是重儿子
    {
        for(int i=0;i<p[u].size();i++)
            if(p[u][i]!=fa[u]&&p[u][i]!=son[u])
                dfs2(p[u][i],0);
        if(son[u])dfs2(son[u],1);
        merge(u,son[u]);//合并
        cal(u);//计算
        if(!is)clear(u);//轻儿子则清除更新
    }
    

    关于时间复杂度:

    根节点到树上任意节点的轻便数不超过 (logn),对于每个轻儿子,会遍历的它子树包含的所有的点,所以总的时间复杂度是 (mathcal{O(nlogn)})

    遇到的例题:

    阔力梯的树

    合约数

  • 相关阅读:
    配置hbase
    hive配置
    scala及spark配置
    Eclipse 配置hadoop
    腾讯云部署hadoop
    助教总结
    预习非数值数据的编码方式
    预习原码补码
    学习java的第六周
    作业一总结
  • 原文地址:https://www.cnblogs.com/kkkek/p/12665361.html
Copyright © 2020-2023  润新知