zoukankan      html  css  js  c++  java
  • 学习笔记--树链剖分

    潇爷的讲解。。十分的nice,可惜人傻。。。然而YveH似乎很早就A过一道题。。。。现在开始学。。。
    

    树链剖分就是兹辞把一棵树上的信息,切成多条链,再把这些链hash到某数据上,是之兹辞对原树上的信息进行快速的查询与修改。
    把树上的路径分类为重链和轻链

    PS此处为链剖线段树QwQ
    定义:
    记size[v]表示以v为根的子树的节点数,deep[v]表示v的深度(根深度为1),top[v]表示v所在的链的顶端节点,fa[v]表示v的父亲,son[v]表示与v在同一重链上的v的儿子节点(称为重儿子),w[v]表示v与其父亲节点的连边(称为v的父边)在线段树中的位置。只要把这些东西求出来,就能用logn的时间完成原问题中的操作。

    **重儿子:**siz[u]为v的子节点中siz值最大的,那么u就是v的重儿子。
    轻儿子:v的其它子节点。
    重边:点v与其重儿子的连边。
    轻边:点v与其轻儿子的连边。
    重链:由重边连成的路径。
    轻链:轻边。

    剖分后的树有如下性质:
    性质1:如果(v,u)为轻边,则siz[u] * 2 < siz[v];
    性质2:从根到某一点的路径上轻链、重链的个数都不大于logn。

    预处理:(dfs_1 && dfs_2)
    dfs_1:
    求出树上每个节点的深度deep[i],根的子树大小size[i],祖先的信息fa[i].以及son[i]之类的信息.
    dfs_2:
    以根为起点,向下拓展建重链,选择最大的子树继承,其余节点以该节点为起点重新做重链;
    给每个点编号,每条重链相当于区间,用数据结构维护这区间,重链首尾相接,维护即可.
    ⒈对于v,当son[v]存在(即v不是叶子节点)时,显然有top[son[v]] = top[v]。线段树中,v的重边应当在v的父边的后面,记w[son[v]] = totw+1,totw表示最后加入的一条边在线段树中的位置。此时,为了使一条重链各边在线段树中连续分布,应当进行dfs_2(son[v]);
    ⒉对于v的各个轻儿子u,显然有top[u] = u,并且w[u] = totw+1,进行dfs_2过程。
    这就求出了top和w。
    将树中各边的权值在线段树中更新,建链和建线段树的过程就完成了。

    具体代码:

    void dfs_1(int now,int f,int d)
    {
        deep[now]=d;fa[now]=f;num[now]=1;
        for (int i=end[now]; i; i=edge[i].next)
            {
                int go=edge[i].go;if (go==f) continue;
                dfs_1(go,now,d+1);num[now]+=num[go];
                if (!son[now] || num[go]>num[son[now]]) son[now]=go;
            }
    }
    void dfs_2(int now,int number)
    {
        top[now]=number;tree[now]=++tot;
        pre[tree[now]]=now;
        if (!son[now]) return;
        dfs_2(son[now],number);
        for (int i=end[now]; i; i=edge[i].next)
            {
                int go=edge[i].go;
                if (go!=son[now] && go!=fa[now]) dfs_2(go,go);
            }
    }

    修改:
    1.点修改 :根据编号在数据结构中修改
    2.区间修改:(1)若L,R在一条重链上,直接修改loc[L]-loc[R]
    (2)若L,R不在一条重链,一边进行修改,一边同时向上靠,靠的同一条重链上,变为情况(1)
    查询操作同上…

    链剖线段树模板题:(不稳定传送门)http://blog.csdn.net/dad3zz/article/details/50627897

  • 相关阅读:
    [kuangbin带你飞]专题十二 基础DP1
    bits/stdc++.h
    第七届 山东省ACM Execution of Paladin(水题)
    poj 1523 SPF【点双连通求去掉割点后bcc个数】
    hdoj 5112 A Curious Matt
    【转】我,一个写代码的
    poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】
    数据结构第二次上机实验【链表实现多项式的加法和乘法】
    hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
    hdoj 3849 By Recognizing These Guys, We Find Social Networks Useful【双连通分量求桥&&输出桥&&字符串处理】
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346212.html
Copyright © 2011-2022 走看看