VOOZH about

URL: https://www.geeksforgeeks.org/dsa/binary-lifting-guide-for-competitive-programming/

⇱ Binary Lifting - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Binary Lifting

Last Updated : 21 Apr, 2026

Binary Lifting is a Dynamic Programming approach for trees where we precompute some ancestors of every node. It is used to answer a large number of queries where in each query we need to find an arbitrary ancestor of any node in a tree in logarithmic time.

👁 binary-lift

The idea behind Binary Lifting:

1. Preprocessing in Binary Lifting:

In preprocessing, we initialize the ancestor[][] table, such that ancestor[i][j] stores the 2^jth ancestor of node i.

  • Initially, we set all the cells of ancestor[][] table = -1.
  • Run a DFS to initialize the immediate parent, that is we initialize ancestor[i][0] for all the nodes.
  • Now, we have initialized the first column of our ancestor table. For all the remaining columns, we can use the following recursive formula,

ancestor[i][j] = ancestor[ancestor[i][j-1]][j-1], when ancestor[i][j-1] != -1

The idea is that we can reach (2^j)th ancestor of node i, by making 2 jumps of size (2^(j-1)), that is (2^j) = (2^(j-1)) + (2^(j-1)). After the first jump from node i, we will reach ancestor[i][j-1] and after the 2nd jump from node ancestor[i][j-1], we will reach ancestor[ancestor[i][j-1]][j-1]

2. Handling Queries in Binary Lifting:

Let's say we need to find 100th ancestor of node X, but in the ancestor[][] table we only have 1st, 2nd, 4th, 8th, 16th, 32nd, 64th, 128th .... ancestors of the current node. Now, we will jump to the maximum possible ancestor such that we don't exceed the 100th ancestor (Safe Jump). So, we will jump to the 64th ancestor of the current node. Now, the problem is reduced to finding the (100-64) = 36th ancestor of this node. We can again jump to the maximum possible ancestor which does not exceed 36, that is 32. We keep on doing this till we reach the required node. In order to find the next safe jump, we can use the binary representation of K. Move from the most significant bit to least significant bit and for every set bit j, we take a jump from this node to the (2^j)th ancestor of the node, which is already stored in ancestor[i][j].

For 100th ancestor of node X,
(100)10 = (1100100)2

👁 Binary-Lifting-in-Competitive-Programming

So, to calculate 100th ancestor of Node X,
Move to 64th ancestor of X = ancestor[X][6] = A1
Then, to calculate the 36th ancestor of A1,
Move to the 32nd ancestor of Aancestor[A1][5] = A2
Then, to calculate the 4th ancestor of A2,
Move to the 4th ancestor of Aancestor[A2][2] = A3


Output
3
4
1
-1

Time Complexity: O(N*log(N) + Q*log(N)), where N is the number of nodes and Q is the number of queries.
Space Complexity: O(N*logN)

Why to use Binary Lifting?

Suppose we have a tree with N number of nodes, and we need to answer queries Q, wherein for each query we need to find an arbitrary ancestor of any node, we can solve it using the following techniques:

  • We can run a DFS and maintain a parent array par[], such that par[i] stores the immediate parent of node i. Now, if we need to calculate the Kth ancestor of any node, we run a loop K times and in each loop, we move to the parent of the current node and after K iterations, we will have our Kth ancestor. This way, we need to run a loop for every query, so the overall time complexity will be O(Q * N), which is quite inefficient.
  • We can pre-compute all the ancestors of every node in a 2D array ancestor[N][N], such that ancestor[i][j] will store the jth ancestor of node i. This precomputation will take O(N * N + Q) time and O(N*N) space but after the precomputation, we can answer every query in O(1) time. This approach is useful when the number of queries is quite large as compared to the number of nodes but if the number of nodes is in the range 10^5, then this approach will exceed the time limit.
  • Instead of precomputing all the ancestors of every node, we can store some specific ancestors of every node. We can maintain a 2D array ancestor[N][logN+1], such that ancestor[i][j] stores the (2 ^ j)th ancestor of node i. Since for each node we are only storing those ancestors which are perfect powers of 2, the space and time complexity to precompute the ancestor table will be reduced to O(N * logN) but to answer each query we will need O(logN) time. So, the overall time complexity will be O(N * logN + Q * log)

Use Cases of Binary Lifting:

1. To calculate arbitrary Ancestor node of any node:

Binary Lifting is used to answer a large number of queries such that in each query we need to calculate an arbitrary ancestor of any node. We have already covered this in the above implementation.

2. To calculate the Lowest Common Ancestor (LCA) of two nodes in a tree:

Binary Lifting is also used to calculate the Lowest Common Ancestor of 2 nodes in a tree. Refer this article to know about calculating LCA using Binary Lifting.

3. To calculate path aggregates in a tree:

Binary Lifting is also used to extract information about the paths in a tree. This can be done by altering the ancestor[][] table by storing extra information in it. Suppose we are given a weighted tree and Q queries. In each query, we are given 2 nodes (X and Y) and we need to find the maximum of all the edges which lie in the path from X to Y. We can solve this problem by storing additional information in the ancestor[][] table. Earlier, ancestor[i][j] stores only (2^j)th ancestor of node i, now we will also store the maximum of all the edges which lie in the path when we jump from node i to (2^j)th node. Now, to calculate the answer, we find the LCA(X, Y) and then divide the path into 2 parts: Path from node X to LCA(X, Y) and Path from LCA(X, Y) to node Y. Now, we return the maximum of both the paths.


Output
0 6 3 4 4 4 5 
6 0 6 6 6 6 6 
3 6 0 4 4 4 5 
4 6 4 0 2 1 5 
4 6 4 2 0 2 5 
4 6 4 1 2 0 5 
5 6 5 5 5 5 0 

Time Complexity: O(N*logN + Q*logN), where N is the number of nodes and Q is the number of queries.
Auxiliary Space: O(N*logN)

Practice Problems on Binary Lifting for Competitive Programming:

Problem

Problem Link

Lowest Common Ancestor in a Binary Tree

Practice Now

Kth Ancestor in a Tree

Practice Now

Find distance between two nodes of a Binary Tree

Practice Now

Optimal Construction of Roads

Practice Now

Longest Subarray with given conditions

Practice Now

Find Edge Weights in a Spanning Tree with Edge (u, v)

Practice Now

Comment
Article Tags:
Article Tags: