前言
作者讨论目前自己遇到的这一类问题的相关做法,并不代表没有更一般的问题和更优秀的做法,欢迎补充。
路径求交
因为这样类似的问题似乎很常见,所以这里讨论一下。
树上路径求交
给出两条路径 ((a,b),(c,d)) 四个点两两求 (LCA),得到 (x_1=lca(a,c),x_2=lca(a,d),x_3=lca(b,c),x_4=lca(b,d))
从这四个点钟选择两个深度最大的点 (p_1,p_2) 若 (p_1 eq p_2) 那么一定有交 交点分别为 (p_1,p_2)
若 (p_1=p_2) 且 (p_1) 的深度小于 (lca(a,b)) 或 (lca(c,d)) 那么两条路径无交点 否则交点为 (p_1)
复杂度瓶颈在于求 (lca) 。
例题:
BZOJ3589 动态树(其实是需要转化才能变成求交的,详见下文)
路径求并
树上路径求并
根据容斥原理,我们可以把路径求并转化为路径求交,也就是这个公式:
集合 (S) 中至少具有性质 (large P_1,P_2,...,P_m) 之一的对象个数为 :
(large |A_1cup A_2cup ... cup A_m|=sumlimits_{{i}}{|A_i|}-sumlimits_{{i,j}}{|A_icap A_j|}+sumlimits_{{i,j,k}}{|A_icap A_jcap A_k|}+...+(-1)^{m+1}|A_1cap A_2cap ... cap A_m|)
但是这样做的弊端在于把问题变成了 (2^m) 个集合求交问题,所以这样做的复杂度是 (O(2^m imes k)) ,其中 (k) 是求一次两点 (lca) 的复杂度,(m) 是这次路径求并的路径条数。
例题:
树上直径合并
给出两颗树,并分别知道它们的直径两点,新的直径一定诞生在四个点的两两组合当中。
根据直径的性质来贪心可以证明。
复杂度瓶颈同样在于求 (lca) 。
例题:暂无。
一点其它的做法
似乎都可以使用 (bitset) 来暴力做这些问题,但是复杂度似乎不太理想。