树剖

接dfs序。 https://www.cnblogs.com/ybjnb/p/19089551
树剖 (dfs序的性质依旧满足 即子树也是一段连续区间)

  1. 将一颗树转化为一个序列
  2. 将树上任意一条路径转化成 log(n) 段连续区间
    然后就可以用序列数据结构维护信息。
    对于u节点 他有子树y1, y2, y3...yk。 考虑将其中siz[yi]最大的那颗子树称之为重儿子。 若有相同任意即可
    重儿子和父节点的连边叫做重边, 其余叫做轻边
    重链: 极大的仅由重边构成的路径
    每个点都在一条重链里面。
    重儿子在他父亲的那一条重链
    轻儿子在以他为开头的往下走的那条重链 (5, 8单独就是一条重链)
    image
    给每个点的编号就是dfs序, 不过dfs时要优先遍历重儿子。
    一条结论:这样编完号之后,树上任意一条路径都可以被转化成 O(log(n)) 段连续区间(重链)。 (最上面的重链可能不完整)
    优先遍历重儿子可以保证每条重链的编号是连续的。
    第一次dfs得到重儿子, 第二次dfs得到dfs序(标记每条重链 标记每个点所在的重链的顶点)
    如何将一条路径转化成若干区间呢?
    x y谁的dep深谁就往上跳重链 直到相汇
    image
inline void xg(int x, int y)
{
    while(tp[x] != tp[y])
    {
        if(dep[tp[x]] < dep[tp[y]]) swap(x, y);
        modify(1, 1, n, id[tp[x]], id[x], 1);
        x = fa[tp[x]];
    }
    if(dep[x] < dep[y]) swap(x, y);
    if(x == y) return;
    modify(1, 1, n, id[y] + 1, id[x], 1);
}

这是把边权挂在下面的点上的写法,细节就是最后处理lca时不要将lca这个点加上 所以是id[y]+1, id[x]

posted @ 2025-11-05 22:55  闫柏军  阅读(4)  评论(0)    收藏  举报