新姿势 树剖求LCA
倍增是求LCA用的最多的算法板子,但是一直不会手拍,但是最近发现了一个新姿势,就是树剖求LCA,发现新大陆
树剖代码:
void Dfs1(int u,int f){ fa[u]=f; siz[u]=1; dep[u]=dep[f]+1; for(int i=head[u]; i!=-1; i=nex[i]){ int v=to[i]; if(v==f) continue; Dfs1(v,u); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]){ son[u]=v; } } } void Dfs2(int u, int tp){ tip[u]=tot++; top[u]=tp; if(son[u]) Dfs2(son[u],tp); for(int i=head[u]; i!=-1; i=nex[i]){ int v=to[i]; if(son[u]==v||v==fa[u]) continue; Dfs2(v,v); } }
那么怎么用树剖求LCA呢?
这个时候就要祭出区间操作的代码了
void get_sum(int u,int v,int n){ int ans=0; while(top[u]!=top[v]){ if(dep[top[v]]<dep[top[u]]) swap(u,v); ans+=query_sum(1,tip[top[v]],tip[v],1,n); v=fa[top[v]]; } if(de[u]<de[v]) swap(u,v); ans+=query_sum(1,tip[v],tip[u],1,n); printf("%d\n",ans); }
这段代码什么意思呢,很明显,树剖后映射到线段树后区间求和嘛,通过这个代码可以知道,区间求和是每次在u v中找一条top深度大重链经行的计算,然后更新u,这样反复知道top相同。。。发现什么了没有,top相同,说明一定在同一条重链上说明一定在同一条链上,那么,深度小的就是LCA了
代码:
int LCA(int u,int v){ int ans=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) swap(u,v); u=fa[top[u]]; } if(dep[u]>dep[v]) swap(u,v); return u; }