树链剖分的作用
树链剖分用于解决树上区间询问,主要有两种:
给出两点,询问和修改之间的路径,
又或者给出一个点,询问和修改整颗子树的信息。
树链剖分需要配合其他数据结构如线段树等一起使用
说白了,树链剖分只是根据询问提供正确的区间
针对路径给出区间 的 复杂度为O(logN)
针对子树给出区间 的 复杂度为O(1)
如何实现?
树链剖分,顾名思义,就是把树分成链。
分为重链和轻链,重链就是重儿子连成的链,轻链就是轻儿子连成的链
对于一个点来说,重儿子就是子节点最多的儿子,其他儿子都叫轻儿子。
然后求出下面这些信息就可以实现我们的树链剖分了
int top[N];//表示该点所在的链的最顶端的点是哪个
int size[N];//该点所在的子树的大小
int fa[N];//父节点
int son[N];//重儿子(子节点最多的儿子)
int id[N];//这个节点实际在区间中的位置,就是dfs过程第一次被访问到的时间,就是dfs序啦
int dep[N];//该节点的深度
顺便来个图:
然后怎么求呢?两个dfs即可解决,多的不说,自己看代码(建树用的是链式前向星)
void dfs1(int now,int f,int nowdep){///处理轻重儿子
dep[now] = nowdep;
fa[now] = f;
size[now] = 1;
for (int i=head[now];i!=0;i=edge[i].last){
int v = edge[i].to;
if (v==f) continue;
dfs1(v,now,nowdep+1);
size[now] += size[v];
if (size[v] > size[son[now]]) son[now] = v;
}
}
int tot;
void dfs2(int now,int topf){///处理轻重边
id[now] = tot++;
a[id[now]] = w[now]%mod;
top[now] &#