标签:子节点 区间修改 return top void style 节点 选择 ++
复杂度nlog2n
边权可以转化成点权 搞一个根 把边权给到边两端深度大的哪个点 这样处理要删一个点 要删的是lca(x,y)
第一步
处理出fa deep size son
void dfs1(int u,int fa,int depth) //当前节点、父节点、层次深度 { f[u]=fa; d[u]=depth; size[u]=1; //这个点本身size=1 for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v==fa) continue; dfs1(v,u,depth+1); //层次深度+1 size[u]+=size[v]; //子节点的size已被处理,用它来更新父节点的size if(size[v]>size[son[u]]) son[u]=v; //选取size最大的作为重儿子 } } //进入 dfs1(root,0,1);
第二步
连接重链 处理出top dfn rk 注意先处理重链再处理轻链 保证了重链的dfn值连续
void dfs2(int u,int t) //当前节点、重链顶端 { top[u]=t; id[u]=++cnt; //标记dfs序 rk[cnt]=u; //序号cnt对应节点u if(!son[u]) return; dfs2(son[u],t); /*我们选择优先进入重儿子来保证一条重链上各个节点dfs序连续, 一个点和它的重儿子处于同一条重链,所以重儿子所在重链的顶端还是t*/ for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v!=son[u]&&v!=f[u]) dfs2(v,v); //一个点位于轻链底端,那么它的top必然是它本身 } }
求lca步骤:
如果两个是在一个重链上的(top相同) 直接选深度小的哪个为lca
否则的话每次选两个节点中top深度深的哪个节点跳
修改步骤:
如果和lca有关的话因为dfn是连续的 就相当于在跳的过程中的每个区间都区间修改区间查询 复杂度是log2n
如果是和子树有关的话 就只是和dfs序有关了 也是区间修改区间查询
标签:子节点 区间修改 return top void style 节点 选择 ++
原文地址:https://www.cnblogs.com/Aragaki/p/9387548.html