Heavy-light decomposition, or HLD, divides a rooted tree into chains. Its main property is that any path between two vertices passes through only O(logn) chains. This lets us process a tree path as a small number of array intervals.
We work with a tree whose edges do not change.
Let size(v) be the number of vertices in the subtree of v, including v itself:
A leaf has subtree size 1. For any other vertex, we add the sizes of its children's subtrees and then count the vertex itself. A DFS computes these sizes by processing the children before their parent.
At each vertex that has children, choose a child with the largest subtree.
The chosen child is the heavy child, and the edge to it is a heavy edge.
The edges to all other children are light edges.
If several children share the largest subtree size, we may choose any one of them. In our example, we break ties by choosing the smaller vertex number.
The tree below is rooted at vertex 1. Each circle shows the vertex number and its subtree size.
Heavy and light edgesсанҷида бин!
The choice depends on subtree sizes, regardless of the values stored at the vertices.
Heavy chains and their heads
A heavy chain, also called a heavy path, is a path of heavy edges that cannot be extended by another heavy edge at either end. A vertex with no heavy edge incident to it forms a chain by itself.
Heavy edges cannot branch: each vertex has at most one heavy child and one parent. As a result, every vertex belongs to exactly one chain.
The topmost vertex of a chain, closest to the root, is its head. A chain starts at the root or at a vertex whose edge from its parent is light.
Our example has five chains. The head of each chain is filled blue.
Heavy chainsсанҷида бин!
Moving along a heavy edge keeps us in the same chain. Crossing a light edge takes us to another chain.
Check your reasoning
The numbers are always equal under our definition.
Every non-leaf vertex has a heavy child, so a heavy chain can end only at a leaf. Conversely, every leaf is the endpoint of exactly one chain, because each vertex belongs to exactly one chain.
Thus, pairing each chain with its final leaf gives a one-to-one correspondence. Changing a tie may move vertices between chains, but it cannot change the number of leaves or the total number of chains.
Why a path crosses few light edges
Suppose u is a light child of v. Its subtree contains fewer than half the vertices in the subtree of v: size(u)<size(v)/2.
To see why, let h be the heavy child of v. The subtree of h is at least as large as the subtree of u. These two disjoint subtrees, together with v itself, all fit inside the subtree of v.
The light-edge boundсанҷида бин!
Proof of the light-edge bound
Since h is the heavy child, size(h)≥size(u). Counting the parent and the two child subtrees gives
size(v)≥1+size(h)+size(u)≥1+2size(u).
Therefore, size(u)≤(size(v)−1)/2<size(v)/2.
Now follow a path from the root to any vertex. The root's subtree has size n. Every time we descend along a light edge, the current subtree size becomes less than half as large.
After k light edges, the current subtree has size at most n/2k. Since it must contain at least one vertex, k≤⌊log2n⌋.
Each light edge starts a new chain. Therefore, a root-to-vertex path touches at most ⌊log2n⌋+1 chains.
The number of heavy edges along the path does not affect this count: consecutive heavy edges stay inside one chain.
The size guarantee applies to light children. A heavy child is simply a child with the largest subtree; it does not have to contain half of its parent's subtree.
Check your reasoning
The size bound can fail. Consider this tree:
Height and subtree sizeсанҷида бин!
The subtree of vertex 2 is the path 2→4→9, so it has size 3 and height 2. The subtree of vertex 3 has four leaf children, so it has size 5 and height . Here, height means the largest number of edges from the subtree's root to one of its descendants.
Choosing by height makes 2 the heavy child of 1. The edge to 3 would then be light, even though size(3)=5>size(1)/2=9/2.
The original rule chooses 3. The halving proof needs a sibling with at least as many vertices as the light child's subtree; a taller sibling does not guarantee that.
A path between any two vertices
Let w be the lowest common ancestor of u and v: the deepest vertex that is an ancestor of both.
The path from u to v goes upward from u to w, then downward from w to v. Each part lies on a root-to-vertex path, so each crosses only O(logn) light edges. The whole path therefore consists of O(logn) chain portions.
Within each chain, the path uses a consecutive portion. It cannot leave a chain and later re-enter it, because that would give two different routes between vertices in a tree.
The path from 8 to 11 is highlighted below. Dashed blue edges separate the chain portions.
A path split into chainsсанҷида бин!
In path order, the three portions are (8,4), (2,1), and (3,7,11).
The light edges between 4 and 2, and between 1 and 3, separate these portions. Each path vertex appears exactly once.
A portion may use only part of its chain. Here, vertices 5 and 9 belong to the same chain as 1 and 2, but they are outside the query path.
Check your reasoning
Eight vertices are not enough. The minimum is 15.
Work backward from the endpoint. Its subtree contains at least 1 vertex. At every light edge, the parent must contain the light child's subtree, a heavy child's subtree of at least the same size, and the parent itself.
If the light child's subtree has at least t vertices, its parent therefore has at least 2t+1. Working upward across the three light edges gives minimum subtree sizes 1, then 3, then 7, then 15. Any heavy edges between them can only increase the required sizes.
To achieve 15, use a complete binary tree with four levels. The two child subtrees at each internal vertex have equal sizes, so we may choose every left child as heavy:
Three light edgesсанҷида бин!
Every edge on 1→3→7→15 goes to a right child and is light. The path therefore crosses exactly three light edges.
The earlier logarithmic bound is valid, but it is not always tight for a particular value of n. Proving a lower bound and giving a matching construction identifies the exact minimum here.
Connecting chains to range queries
When we assign consecutive array positions to the vertices of each chain, every chain portion becomes one array interval.
A tree path then becomes O(logn) intervals. For a path-maximum query, we find the maximum on each interval and combine the results. With a segment tree, each interval query takes O(logn) time, giving O(log2n) time for the full path query.
The next lesson shows how to assign these positions and find the intervals using chain heads.
You will learn
Choose heavy and light edges using subtree sizes.
Divide a rooted tree into heavy chains and identify their heads.
Explain why any path consists of only O(logn) chain portions.
Activity
Our example has five leaves and five heavy chains. Is this a coincidence, or must the number of chains always equal the number of leaves? Prove your claim or find a counterexample. Could changing how ties are broken change the total number of chains?
Think again
A student proposes choosing the child whose subtree has the greatest height instead of the greatest size. Would every light child still contain fewer than half of its parent's subtree vertices? Construct a counterexample with no tie in height, or explain why one cannot exist.
Extra challenge
The bound k≤⌊log2n⌋ does not rule out three light edges in a tree with 8 vertices. Can a root-to-vertex path in such a tree actually cross three light edges? Find the smallest tree that can, and justify both why fewer vertices are impossible and why your construction works.