樹鏈剖分邊權轉化為點權
阿新 • • 發佈:2020-11-14
現在給出將樹鏈剖分上的邊權轉化為點權的方法
也就是將邊權轉到它下方的點去
我們通過畫圖可以發現,這樣的話,我們會多算最近公共祖先上方的點
方法一:先不考慮的多算的部分,還按原來的方法來,在之後消除最近公共祖先的影響
我們只需要在原來的程式碼基礎上將\(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 不然會一直遞迴下去,發生段錯誤