build a tree traversal array with node and depth, including circling back up. find node with minimum depth between two nodes to find least common ancestor. do fast rmqs using segtree or sparse table

vector<pair<int, int>> depth;
vector<int> first;
 
void dfs(int u, int d) {
    if (first[u] == -1) first[u] = depth.size();
    depth.push_back({d, u});
 
    for (int v : graph[u]) {
        dfs(v, d + 1);
        depth.push_back({d, u});
    }
}
 
first.assign(n, -1);
dfs(0, 0);
 
auto combine = [](pair<int, int> a, pair<int, int> b) { return min(a, b); };
SparseTable<pair<int, int>, decltype(combine)> st(depth, combine);
 
// lca of some nodes x and y
int l = first[x];
int r = first[y];
if (l > r) swap(l, r);
int lca = st.range(l, r).second;

distances between nodes

with as lca of nodes and , can compute distance using formula

milk visits

  • run dfs for lca
  • while running, store list of changes of type at each entry/exit time point as
  • get lca for nodes and
  • define as getting lowest node of type when dfs was at , by finding the pair with the greatest , i.e. upper_bound
  • get the depth of that lowest node and check if that
  • if it is, then the condition succeeds, since there is a node on the path between and the
  • repeat these same steps for the other node