【题目链接】
【思路要点】
- 考虑枚举最终路径的一端 x x x ,那么路径的另一端 y y y 应当在所有过 x x x 的路径的并上,也即这些路径两端所有点形成的虚树上,因此,我们需要知道这个虚树的大小。
- 注意到虚树大小即为将点按照 d f s dfs dfs 序环形排列后相邻的点在原树上距离和的一半,可以用线段树维护 d f s dfs dfs 序,记录区间最左、最右侧的点,以及区间相邻点的距离和,即可支持加点和删点。
- 用线段树合并即可计算答案,为保证复杂度,需要用 S T ST ST 表预处理后 O ( 1 ) O(1) O(1) 询问 L c a Lca Lca 。
- 时间复杂度 O ( N L o g N + M L o g N ) O(NLogN+MLogN) O(NLogN+MLogN) 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 5; const int MAXP = 8e6 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) { x = max(x, y); } template <typename T> void chkmin(T &x, T y) { x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f