树链剖分边权转化为点权

现在给出将树链剖分上的边权转化为点权的方法

也就是将边权转到它下方的点去

我们通过画图可以发现,这样的话,我们会多算最近公共祖先上方的点

方法一:先不考虑的多算的部分,还按原来的方法来,在之后消除最近公共祖先的影响

我们只需要在原来的代码基础上将(query \_ path)改成

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+=query(1,id[top[u]],id[u]);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	ans+=query(1,id[v],id[u]);
	ans-=query(1,id[v],id[v]);//深度较浅的点id[v]是最近公共祖先
	return ans;
}

(updatp\_ path)改成

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

方法二

直接在修改和查询操作的时候,不将最近公共祖先算进去就行

这个是由我们的(dfs)序决定的

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+=query(1,id[top[u]],id[u]);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	ans+=query(1,id[v]+1,id[u]);
	return ans;
}

(update \_ path)

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

注意

在递归的时候记得检查一下我们在递归到最底层的时候,我们是否return 不然会一直递归下去,发生段错误

原文地址:https://www.cnblogs.com/bangdexuanyuan/p/13974638.html