加载中…

返回上一页

树链剖分

不是联赛内容,但是用得多,就先整着

树链剖分

树剖,其实就是将一棵树剖成若干条链,来解决树上的路径问题.

剖成链有什么用呢?主要是把它组合成一个线性结构,然后拿数据结构去维护.

下面主要讲的是重链剖分,因为长链剖分一般很少涉及到,以后有涉及再写.

维护几个信息:

  1. 重儿子 son[x]:点 x 的子节点中子树最大的子节点,从 xson[x] 的边称为重边

  2. 子树大小 siz[x]:以点 x 为根的子树大小(节点数);

  3. dfsdfn[x]:这个没什么好说的;

  4. 链顶点 top[x]:点 x 所在重链的顶部节点.

一共需要进行两遍 dfs 操作,第一遍进行找重边,第二遍进行连接重边.

实现

inline void dfs1(ll x,ll fa)
{
	f[x]=fa;dep[x]=dep[fa]+1;siz[x]=1;son[x]=0;
	for(rll i=0;i<g[x].size();i++)
	{
		rll to=e[i].to;if(to==fa) continue; dfs1(to,x);siz[x]+=siz[to];
		if(siz[to]>siz[son[x]]) son[x]=to;
	}
}
inline void dfs2(ll x,ll fa)
{
	dfn[x]=++cnt;top[x]=fa; if(son[x]) dfs2(son[x],fa);
	for(rll i=0;i<g[x].size();i++) { rll to=e[i].to; if(dfn[to]) continue; dfs2(to,to); }
}

剖分完之后就可以用数据结构去维护每一个链,就相当于维护每一个区间.

修改操作

当要修改的区间在同一条重链上时,直接用数据结构进行区间修改;如果不在,就需要把它们不断往一条链上靠.

怎么进行?

设两个点分别为 xy. 如果点 x 所在重链顶端的点的父亲y 处在同一条重链上,那就把点 xtop[x] 间的权值进行修改,跳上去再修改就行了.
如果出现需要经过多条重链的,就不断进行上述操作.

如果都要向上跳呢?

每次找到 dep[top[i]] 更大的 i 去修改从 itop[i] 间每个点的权值,不断向上跳直至到达同一条重链.

实现:

inline void modify(rll x,rll y,rll v)
{
	while(top[x]^top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		upd(dfn[top[x]],dfn[x],v);// 使用数据结构实现区间修改
		x=top[x];
	}
	if(dep[x]>dep[y]) swap(x,y);
	upd(dfn[x],dfn[y],v);// 使用数据结构实现区间修改
}

LCA

最近公共祖先.

两种常用的求 LCA 方法

  1. 倍增

这不是树剖嘛我怎么在写倍增

二进制是个好东西,倍增思想充分利用了这个特点.

fa[i][j] 表示点 i2j 层祖先.

方法就是:fa[i][j]=fa[fa[i][j-1]][j-1].

fa[i][0] 就是 i 的父亲节点了.

LCA

也是利用二进制拆分,把深度大的点不断进行节点上翻 if(fa[i][j]) i=fa[i][j];.

然后在同一层时把两个点同时向上翻,直至 fa[x][0]=fa[y][0]. 那么 fa[x][0] 就是 LCA.

实现

inline ll getd(rll x,rll y)
{
	for(rll i=0;i<=16;i++) if((1<<i)&y) x=fa[x][i];
	return x;
}
inline ll lca(rll x,rll y)
{
	if(x==1||y==1) return 1; if(dep[x]<dep[y]) swap(x,y);
	x=getd(x,dep[x]-dep[y]); if(x==y) return x;
	for(rll i=16;~i;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
  1. 树剖

和上面树剖查询的类似. 也是不断往一条重链上靠.

实现

inline ll lca(rll x,rll y)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=f[top[x]];
	}
	if(dep[x]<dep[y]) return x; return y;
}
posted @ 2022-10-11 06:48  1Liu  阅读(15)  评论(0)    收藏  举报