Explanation
First, we need to divide queries into two types: those that require us to jump to the root, and those that don't require such. Let's consider a query for the shortest path .
Case 1: is an ancestor of
The optimal solution is for our path to just walk downwards from to . This is equivalent to , where is the root of our tree. To answer these queries, we use the method described in this editorial.
Case 2: is not an ancestor of
In this scenario, our path from to has the following structure.
- First, we traverse down to some node in the subtree of
- Using the back edge at our chosen node, we jump to node .
- Finally, we walk down to node
We can use the same code for case 1 to calculate . However, it isn't exactly clear how we should figure out the best node to pick in the subtree of to jump from. Let the node we traverse down to be . Then, the cost of using node to jump to the root is:
Here, refers to the cost of jumping from to the root. Using the same idea from case 1, we can change our expression a bit.
The distance from the root to node is fixed here. Thus, we want to find the best value of within the subtree of . To do this, we use Euler Tour to flatten our tree, and then use a lazy segment tree to answer our queries.
Our segment tree must support range addition and range minimum. For more information on how to implement it, refer to the Range Updates Range Queries module.
Handling Updates
If the edge we are updating is from node to node , then it only affects the value in our segment tree for node . Thus, we do a point update on the node in question.
In the case that the edge we are updating isn't from some node to the root, then it changes all the values inside the subtree it affects. Let's have the edge affected connect node and node , with the difference in weight being . Then, we must do the following.
- Change the distances in the subtree of by
- Change the value of by
In my code, this boils down to updating the binary indexed tree handling the root to node distances, and updating the segment tree containing the value of for every node.
Implementation
Time Complexity:
C++
#include <bits/stdc++.h>using namespace std;using ll = long long;Code Snippet: Lazy Segment Tree (from the module) (Click to expand)Code Snippet: BIT (from the module) (Click to expand)int main() {
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!