树链剖分的一个小细节
做树链剖分最头疼的就是LCA的特殊性,有必要自己证明一下,否则用着不踏实,以求x到y的sum为例,z=lca(x,y)
procedure solvesum; begin ans:=0; while ch<>' ' do read(ch); readln(x,y); while top[x]<>top[y] do begin if dep[top[x]]<dep[top[y]] then swap(x,y); inc(ans,getsum(1,p[top[x]],p[x])); x:=fa[top[x]]; end; if dep[x]>dep[y] then swap(x,y); inc(ans,getsum(1,p[x],p[y])); writeln(ans); end;
一个显而易见的结论是 若x处于y的子树中,那么dep[top[x]]<=dep[top[y]]当且仅当top[x]=top[y]即x,y处于同一条重链上=成立
1.若 top[x]=top[y] 说明x,y在同一条重链上,求和sum(p[x],p[y])即可 (p[x]<p[y])
2.若top[x]!=top[y]且x,y都不在z向下的重链上,那么往上提的时候一定有一个点不妨设为x通过x=fa[top[x]]操作到达z的重链上,并且没有计算这条链上的贡献
这样dep[top[x]]达到最小值,x不会再往上提,直到另一个节点通过同样的操作到达z的重链上,并且没有计算,
这时候必有x,y之一=z,dep值小的就是LCAz
这时候退出while,在外层ans+=sum(p[x],p[y])即可,p[x]<p[y]
3.若top[x]!=top[x]且x,y中有一个处于以z向下的重链上,不妨设为x,那么一开始dep[top[x]]达到最小值,只会调整y,直到y通过fa[top[y]]到达z的重链上
此时也没有计算z的重链,退出while之后计算即可类似于2计算即可
忽然发现自己写了这么多证了一个多么sb的问题。。。
所以貌似 月下毛景树那一题也可以不求LCA搞,去试试。。。。
总之归根结底就是一句话:
退出while之后 dep小的就是x和y的LCA,并且它的信息还没有被计算过!!!