Suppose we want to support the following operations on a tree:
- Update all nodes along the path from node to node .
- Query the sum, maximum, minimum, or any other operation that satisfies the associative property along the path from node to node .
Heavy Light Decomposition (HLD) supports both of these operations efficiently. Naively performing these operations can be slow on large trees, but HLD decomposes the tree into paths to allow updates and queries in logarithmic time.
| Resources | |||||
|---|---|---|---|---|---|
| cp-algo | For an alternate implementation, see below | ||||
| CF | blog + video for USACO Cowland. Binary jumping isn't necessary though. | ||||
Optional: Tree Queries in O(NQ)
This is why you don't set problems where is intended ...
Tutorial
Definitions
- A heavy child of a node is the child with the largest subtree size rooted at the child.
- A light child of a node is any child that is not the heavy child.
- A heavy edge connects a node to its heavy child.
- A light edge connects a node to any of its light children.
- A heavy path is a maximal and contiguous path formed by only heavy edges. The set of all heavy paths spans every node in the tree.
Note that there is no notion of "light paths" in HLD; light edges simply connect heavy paths to each other.
Properties
Any path from node to node on the tree can pass through at most light edges.
Proof
A heavy path can only be broken by crossing a light edge; otherwise, the heavy path would simply continue on. Because of this, we know there are at most heavy paths on any path from an arbitrary node to an arbitrary node .
Additionally, by using a Segment Tree (or similar structure), we can process queries on a contiguous segment of any heavy chain in time.
Since the process requires performing Segment Tree operations, the total time for a path query or update is . Therefore, we can answer queries in time.
Here's an animation of how the algorithm works:
Implementation
| Resources | |||||
|---|---|---|---|---|---|
| CF | |||||
| CF | not complete | ||||
| Benq | complete implementation following the above two articles with minor modifications | ||||
Below is an example implementation of Heavy Light Decomposition based on the resources above. See the solution below, as well as the solutions for Subtrees & Paths and Query on a tree again!, for examples of how this implementation can be used.
C++
#include <bits/stdc++.h>using namespace std;template <class T, bool VALS_IN_EDGES> class HLD {private:int N, R, tim = 0; // n, root node, timevector<vector<int>> adj;vector<int> par, siz, depth, rt, pos; // parent, size, depth, root, position arraysLazySegtree<T> segtree; // Modify as needed
Path Queries II
Focus Problem – try your best to solve this problem before continuing!
Explanation
We can label each edge as either heavy or light, then use a segment tree to keep track of the maximum value in each heavy chain.
Now, to change the value at node to , we can just update the value in the segment tree. To query the maximum value in the path from to , we first find the Lowest Common Ancestor. We combine the path from to and the path from to to find our answer.
Implementation
Time Complexity: per query
C++
#include <bits/stdc++.h>using namespace std;Code Snippet: Segment Tree (Click to expand)Code Snippet: HLD (Click to expand)int main() {ios_base::sync_with_stdio(false);cin.tie(0);
Problems
| Status | Source | Problem Name | Difficulty | Tags | ||
|---|---|---|---|---|---|---|
| CSES | Easy | Show TagsHLD, LCA | ||||
| Gold | Easy | Show TagsHLD, PURS | ||||
| SPOJ | Easy | Show TagsHLD | ||||
| Gold | Normal | Show TagsHLD | ||||
| Platinum | Normal | Show TagsHLD | ||||
| HR | Normal | Show TagsHLD, RURQ | ||||
| Old Gold | Normal | Show TagsHLD, PURS | ||||
| YS | Normal | Show TagsHLD, SegTree | ||||
| CF | Hard | Show TagsHLD | ||||
| CF | Hard | Show TagsHLD | ||||
| TLX | Hard | Show TagsHLD | ||||
| JOI | Hard | Show TagsHLD | ||||
| JOI | Very Hard | Show TagsHLD | ||||
Warning!
"Grass Planting" isn't submittable on the USACO website. Use this link to submit.
Module Progress:
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!