1. 程式人生 > 實用技巧 >樹鏈剖分邊權轉化為點權

樹鏈剖分邊權轉化為點權

現在給出將樹鏈剖分上的邊權轉化為點權的方法

也就是將邊權轉到它下方的點去

我們通過畫圖可以發現,這樣的話,我們會多算最近公共祖先上方的點

方法一:先不考慮的多算的部分,還按原來的方法來,在之後消除最近公共祖先的影響

我們只需要在原來的程式碼基礎上將\(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 不然會一直遞迴下去,發生段錯誤