voidSolve(){ ll N, M; cin >> N >> M; vector<ll> diff_ls(N + 2); vector<ll> parent(N + 2); for (int i = 1; i <= N - 1; ++i) { parent[i] = i + 1; } for (int i = 1; i <= M; ++i) { ll u, v; cin >> u >> v; parent[u] = max(parent[u], v); } vector<vector<ll> > g(N + 2); for (int i = 1; i <= N - 1; ++i) { g[i].push_back(parent[i]); g[parent[i]].push_back(i); } vector<ll> size_ls(N + 2, 1), heavy_son(N + 2), mx_dep_ls(N+2);
auto dfs1 = [&](auto &&self, ll u, ll p) -> ll { for (auto to: g[u]) { if (to == p) { continue; } size_ls[u] += self(self, to, u); if (size_ls[to] >= size_ls[heavy_son[u]]) { heavy_son[u] = to; } } return size_ls[u]; }; dfs1(dfs1, N, -1); // 我们想要计算的就是,当我们已经知道 一个点 v,在其他 // 所有树上,比他的深度浅或者同样深度的所有点,贡献 dep(u)-dep(lca(u,v)) // 不过只有其他
// dsu on tree vector<map<ll,ll> > node_dep_cnt_mtx(N + 2); ll ans=0; auto dfs2 = [&](auto &&self, ll u, ll p,ll dep) -> void { for (auto to: g[u]) { if (to == p) continue; if (to != heavy_son[u]) continue; self(self, to, u, dep+1); // 复用重儿子的空间,避免 mle。 swap(node_dep_cnt_mtx[u], node_dep_cnt_mtx[to]); break; } ll sum_node=size_ls[heavy_son[u]]; for (auto to: g[u]) { if (to == p) continue; if (to == heavy_son[u]) continue; // 我们先写的 naive 一点 self(self,to,u,dep+1); // 其实只要我们合并的方法只和轻儿子的子树相关性质有关系 // 比如说深度, ll mx_dep=node_dep_cnt_mtx[to].rbegin()->first; // 虽然说比他的深度浅或者同样深度的所有点,贡献 dep(u)-dep(lca(u,v)) // 但比他深度深的节点,也会贡献,因为已经在重儿子中的深度深的节点 // 合并进来的时候还没有这样一个节点,贡献的就是 dep(v)-dep(lca(u,v))