蒟蒻不会边分治……
诶一看这个时限 O(nlog2n) 很有戏啊……
所以?树剖?
首先我们记永恒的树为 T′,Trie 为 T,以及树上的一些相关值带 ′ 表示永恒的树意义的,否则表示在 Trie 上的。
题目求的是 ∑u,v∈T′,u<v∑[x,y]⊆[u,v]depLCA(x,y)
然后有一个简单的思想就是把后面的拉到前面来,即对于 x,y 计算 depLCA(x,y) 并求其出现次数(作为子路径的次数)。
这个就是套路了。
考虑当两者没有祖孙关系时,那么贡献显然就是 size′x⋅size′y。
否则,假设 x 是 y 的祖先,z 是 x→y 路径上除 x 以外离 x 最近的点。
此时贡献是 (n−size′z)size′y。
第一种贡献其实同样比较套路,看到 LCA 的 dep 就想到了「『LNOI2014』LCA」。
所以类似地,枚举 x,并让其到根路径都加上 size′x。
枚举 y,对根路径求和,乘上 size′y。
注意要除掉根的贡献,因为 dep 从 0 开始记。
那么离线一下可以做到 O(n)。
有一个潜在的问题:第二种贡献的点在第一种贡献里也被计算了。
这个先不讨论。
第二种贡献,我们跑一遍 DFS。因为只要确定 x 了,y 一定在 x 的子树当中。
假设当前遍历到的点为 x,枚举其儿子为 z,那么对于 z 子树之内的 y 计算时都是同一个 z。
所以我们就给 x 到根加上 n−size′z,然后每次遍历到点就计算贡献。
注意回溯时要减回去。
然后再来讨论刚才那个问题,我们发现,只需要在 DFS 的过程中把 size′x 对于子树内的贡献除掉即可。
就是说把加的数换成 n−size′z−size′x。
最近复习了下区间查改的树状数组,常数又小,换上了。
反正有取模不会爆。
代码:
1 |
|