P4211 [LNOI2014] LCA 题解
切入这道题,首先要思考所有 LCA 的分布特征。显然,对于任意 \(\text{LCA}(i, j)\),都满足 LCA 是 \(i, j\) 的祖先。那么对于一个询问,可以找到所有 \(i \in [l, r]\) 的祖先,还可以找所有 \(z\) 的祖先。明显,找 \(z\) 的祖先会方便很多:它们都分布在 \(z\) 到根节点的那条链上,这应该会更方便统计,可以用 LCT、树链剖分之类的算法。所以我们从 \(z\) 的祖先着手切入。
先研究任意一个 \(z\) 的祖先 \(x\),试着求出它作为 LCA 时对答案的贡献。
明显,当研究 \(x\) 这棵树时,和 \(z\) 不在一棵子树中的所有节点 \(i\),都满足 \(\text{LCA}(i, z) = x\)。(可能说得比较模糊,反正就是图中 1, 6 节点可以和 \(z\) 有 LCA = x,而节点 3, 5 则不行。)
设 \(x\) 子树中所有节点,满足编号在 \([l, r]\) 间,数量 \(sz(x)\);并且令 \(z\) 在的那棵子树为 \(Z\)。则易得 \(x\) 对答案的贡献为:\(dep(x)*[sz(x)-sz(Z)]\)。
然后,为了快速统计 \(sz(x)\),我当时想出了一个算法:可持久化线段树。可持久化线段树中以每个点的编号为下标。
然而,这个算法仅能对 \(z\) 的祖先们进行逐个计算,而不能实现最终的目的:拓展到链的整体操作上。
于是想:能不能把可持久化线段树去掉?想到离线 + 差分。
把每一个询问拆开,拆成 \(r, z\) 和 \(l-1, z\),