现在给出将树链剖分上的边权转化为点权的方法
也就是将边权转到它下方的点去
我们通过画图可以发现,这样的话,我们会多算最近公共祖先上方的点
方法一:先不考虑的多算的部分,还按原来的方法来,在之后消除最近公共祖先的影响
我们只需要在原来的代码基础上将(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 不然会一直递归下去,发生段错误