Codechef MXMN

题意

codechef

做法一

首先kruskal重构树,那么(f(G_1/G_2,i,j))就转化为(val[G_1/G_2(lca(i,j))])
(G_1)边分,令当前边分出来的边为((u,v)),将该边断开,当前连通块分成(T_1(u),T_2(v))
如果在(G_1)(dep_u<dep_v),那么(xin T_1,yin T_2,lca(x,y)=lca(x,u)),否则反之

那么对(T_1,T_2)的点分别染上黑/白两色,(xin T_1,val_x=val_{lca(x,u)},yin T_2,val_y=1)
对于(T_1cup T_1)(G_2)建虚树,对于(zin G_2,xin T_1,yin T_2,G_2-lca(x,y)=z),贡献为(val[G_2(z)] imes val[G_1(x)] imes val[G_1(y)]),这个很简单搞一个树形dp就好了

(O(nlogn))

做法二

这个做法暂时不太熟练
首先还是建重构树,对于(G_1),令(w(u,fa_u)=val_u-val_{fa_u}),则(val_x=dep_x)
(dis(x,y)=dep(x)+dep(y)-2dep(lca(x,y))Longrightarrow dep(lca(x,y))=frac{1}{2}(dep(x)+dep(y)-dis(x,y)))

那么对于(G_2)上某点(z),其两棵子树分别为(T_1,T_2)(xin T_1,yin T_2),贡献为(val[G_2(z)] imes dep(G_1(lca_{x,y}))=frac{1}{2}val[G_2(z)] imes G_1(dep(x)+dep(y)-dis(x,y)))
(dep(x),dep(y))可以直接根据(T_1,T_2)的子树大小直接算出来,只用考虑(dis(x,y))了,对于(yin T_2)(forall xin T_1)可以通过点分树(O(logn))算出来,然后直接点分树合并就好了。

稍微讲一下点分树合并,开始预处理(G_1)的点分树,然后对于每个点(x),其初始时点分树为点分树上(x)(rt)的路径,合并就跟线段树合并一样。

原文地址:https://www.cnblogs.com/Grice/p/12848835.html