树链剖分总结

所谓树链剖分就是把树上的路径转化为连续的区间从而用各种数据结构解决树上的问题。

而转化为区间则是利用其重链的性质把一条树上的路径变成很多连续的重链从而加速找两点的lca。

并在节点向上跳的过程中对区间用数据结构做更新操作,或是将连续的重链保存做离线操作。

常见的树链剖分有更新链或子树的权值并求其权值。权值也可以换成任何可以在连续区间用数据结构解决的其他询问。

 

一、

首先需要对树进行预处理,通过一次dfs找出每个节点的父亲节点、重儿子节点、以及节点下子树的大小、节点深度。

dep[M]:深度

f[M]:父亲

son[M]:重儿子

sz[M]:子树大小

void dfs(int u,int fa,int d){
    sz[u]=1,dep[u]=d,f[u]=fa,son[u]=-1;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u,d+1);
        sz[u]+=sz[v];//update size
        if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;//子树大小最大的儿子是重儿子
    }
    return ;
}
dfs(1,-1,1)进入
View Code

 

 

二、

由上一步预处理出的信息进而得到每条重链的起始节点为之后的剖分加速。以及处理树的dfs序把所有的子树和重链变为连续的区间。

top[M]:每条重链的起始节点,将重儿子连接起来的链称为重链。

rnk[M]:连续区间中的下标在树中的编号。

id[M]:树中节点在连续区间里的编号。

void dfs1(int u,int t){
    id[u]=++tot;//dfs序
    rnk[tot]=u;
    top[u]=t;//重链上的top都为链的起始节点
    if(son[u]==-1) return ;
    dfs1(son[u],t);//先更新重儿子使得重链是连续的区间
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==f[u]||v==son[u]) continue;
        dfs1(v,v);//轻儿子是其重链的起始节点
    }
    return ;
}

dfs1(1,1)进入
View Code

 

 

三、

将询问的的路径剖分为不同的重链即连续的区间。在连续的区间中可以用各种数据结构搞事情。

void update1(int x,int y,int v){
    int fx=top[x],fy=top[y];//把节点指向其重链的起始节点
    while(fx!=fy){//如果这两个点不在一条重链上则一直向上跳
        if(dep[fx]>dep[fy]){//fx节点深度更深
            update(id[fx],id[x],1,n,1,v);
            x=f[fx],fx=top[x];//从这条重链爬到父节点的重链上去
        }
        else{//同理
            update(id[fy],id[y],1,n,1,v);
            y=f[fy],fy=top[y];
        }
    }
    if(dep[x]<dep[y])//在一条重链中时深度可能不相等
        update(id[x],id[y],1,n,1,v);
    else
        update(id[y],id[x],1,n,1,v);
}

//路径的查询操作与更新操作基本一致。
View Code

 

 

四、

写好数据结构。

 

 

例题:

hdu 3966 Aragorn's Story    区间更新路径权值,单点查询权值。

 

洛谷 3384    区间更新+区间查询。

 

洛谷 2146 软件包管理器    支持链与子树的更新与查询

 

poj 2763 Housewife Wind&&fzu 2082 过路费    处理边权而非点权,边权可以映射到点权里去。

 

poj 3237 Tree    单点更新,区间取反,区间查询。

 

hdu 4718 The LCIS on the Tree    树链剖分+求区间LCIS

 

hdu 5052 Yaoge’s maximum profit     树链剖分+线段树合并

 

hdu 5029 Relief grain     树链剖分+权值线段树

 

转载于:https://www.cnblogs.com/LMissher/p/9568463.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值