树链剖分入门+博客推荐

树链剖分入门博客推荐

网上关于树链剖分的文章很多,自己在学习树链剖分的时候找到了几篇好的文章,代码规范,有图例。树链剖分的部分自己先挖个坑,以后再专门写个博客来总结。

博客推荐

博客一

推荐理由:每个函数完成后的结果都有相应的图例,可以自己模拟一下和图对应,加深对函数功能的理解。

博客二

推荐理由:完整的函数实现,树链剖分+线段树的完整代码。

博客三

推荐理由:代码规范,通俗易懂。

我的常用代码模板

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+7;
struct node{
    int l, r;
    int ans, lazy;
}
struct edge{
    int to, next;
}e[maxn<<1];
int head[maxn], len;
int son[maxn], size[maxn], dep[maxn], fa[maxn];
int top[maxn], inp[maxn], cnt;
void init()
{
    len=cnt=0;
    for(int i=0; i<=n; i++)
        head[i]=-1;
}
void add(int u, int v)
{
    e[len].to=v;
    e[len].next=head[u];
    head[u]=len++;
}
  1. dfs1主要是解决树上点的基本信息
void dfs1(int u, int f, int depth)
{
 	size[u]=1;
    dep[u]=pedth;
    fa[u]=f;
    for(int i=head[u]; i!=-1; i=e[i].next)
    {
        int v=e[i].to;
        if(v==f) continue;
        dfs1(v, u, depth+1);
        size[u]+=size[v];
        if(size[v] > size[son[u]])
            son[u]=v;
    }
}
  1. dfs2是处理dfs序和重链
void dfs2(int u, int tp)
{
    top[u]=tp;
    in[u]=++cnt;
    if(!son[u])
        return;
    dfs2(son[u], tp);
    for(int i=head[u]; i!=-1; i=e[i].next)
    {
        int v=e[i].to;
        if(v==son[u] || v==f[u])
            continue;
        dfs2(v, v);
    }
}
  1. 处理x和y的最近公共祖先
//fx表示x所在链的顶,fy表示y所在链的顶。
void lca(int x, int y)
{
    int fx=top[x], fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx] < dep[fy]) //确保每次更新都是深度大的都是x
        {
            swap(x, y);
            swap(fx, fy);
        }
        x=fa[x];
        fx=top[x];
    }
    return dep[x] < dep[y] ? x:y;
}
  1. 把从x到y的一条最短链上点的值改为z
//把从x到y的最近链上点的值改为z;
void update_chain(int x, int y, int z)
{
    int fx=top[x], fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx] < dep[fy])
        {
            swap(x, y);
            swap(fx, fy);
        }
        update(1, in[fx], in[x], z);
        //每往上跳一次,就修改以次经过路径上的值,因为DFS序中id[fx] < id[x],所以是区间[id[fx],id[x]];
    }
    if(in[x] > id[y]) 
        swap(x, y);
    update(1, in[x], in[y], z);
}
  1. 求从x到y的最近一条链点值的总和。
int query_chain(int x, int y)
{
    int ans=0, fx=top[x], fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx] < dep[fy])
        {
            swap(x, y);
            swap(fx, fy);
        }
        ans+=query(1, in[fx], in[x]);
    }
    if(in[x] > in[y])
        swap(x, y);
    ans+=query(1, in[x], in[y]);
    return ans;
}
欢迎评论交流!
原文地址:https://www.cnblogs.com/alking1001/p/11402131.html