树剖模板

· · 算法·理论

题目:P3384 【模板】重链剖分/树链剖分

传送门:P3384 【模板】重链剖分/树链剖分

代码结构剖分

dfs1

dfs2

所以使用线段树来维护一条重链上的信息。

路径的修改与查询

修改

默认 x 的深度较大,让 x 反复跳向当前所在重链顶端。直到 xy 在同一条重链上。同时对重链上的节点进行线段树区间操作。当满足条件后,还要将 xy 之间的节点修改。

code

inline void update_path(int u,int v,int k){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        update(1,id[top[u]],id[u],k);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    update(1,id[v],id[u],k);
}

查询

与修改相差无几。将函数 update 部分改为 query,对重链进行线段树的区间查询。多加几个变量记录查询结果。

code

long long query_path(int u,int v){
    long long ans=0;
   //根据题目要求进行取模
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans=(ans%p+query(1,id[top[u]],id[u])%p)%p;
     //只需要将update改query再记录答案
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    ans=(ans%p+query(1,id[v],id[u])%p)%p;
    return ans;
}

main 函数部分

对于路径 x\to y

直接 update(x,y)query(x,y)

对于 u 的子树操作

需要操作的范围为 u\to u+size_u-1