# Queries for the number of nodes having values less than V in the subtree of a Node

Given a rooted tree (assume root is 1) of N nodes and Q queries, each of the form (Val, Node). For each query, the task is to find the number of nodes with values smaller than Val in sub-tree of Node, including itself.
Note that by definition, nodes in this tree are unique.
Examples:

```Input: N = 7, Q = 3
Val = 4, Node = 4
Val = 7, Node = 6
Val = 5, Node = 1
Given tree:```

```Output: 2
1
4
Explanation: For given queries:
Q1 -> Val = 4, Node = 4
The required nodes are 2 and 3
Hence the output is 2

Q2 -> Val = 7, Node = 6
The required node is 6 only
Hence the output is 1

Q3 -> Val = 5, Node = 1
The required nodes are 1, 2, 3 and 4
Hence the output is 4```

Naive approach: A simple approach to solve this problem would be to run DFS from a given node for each query and count the number of nodes smaller than the given value. The parent of a given node must be excluded from the DFS
Time complexity: O(N*Q), where Q is the number of queries and N is the number of nodes in the tree.
Efficient Approach: We can reduce the problem of finding the number of elements in a sub-tree to finding them in contiguous segments of an array. To generate such a representation we run a DFS from the root node and push the node into an array when we enter into it the first time and while exiting for the last time. This representation of a tree is known as Euler Tour of the tree.
For example,

The Euler Tour of the above tree will be:

`1 4 2 2 3 3 5 5 4 6 7 7 6 1`

This representation of tree has the property that the sub-tree of every node X is contained within the first and last occurrence of X in the array. Each node appears exactly twice. So counting the number of nodes smaller than Val between the first and last occurrence of Node will give us twice the answer of that query.
Using this representation, the queries can be processed offline in O(log(N)) per query using a binary indexed tree
Pre-processing:

1. We store the index of 1st and last occurrence of each node in the Tour in two arrays, start and end. Let start[X] and end[X] represent these indices for node X. This can be done in O(N)
2. In the Euler Tour we store the position of the element along with node as a pair (indexInTree, indexInTour), and then sort according to indexInTree. Let this array be sortedTour
3. Similarly, we maintain an array of Queries of the form (Val, Node) and sort according to Val. Let this array be sortedQuery
4. Initialize a Binary Indexed Tree of size 2N with all entries as 0. Let this be bit
5. Then proceed as follows. Maintain a pointer each in sortedTour and sortedQuery
6. For each query in sortedQuery from the beginning select the nodes from sortedTour having indexInTree < Val, and increment their indexInTour in bit. Then the answer of that query would be half of the sum from start[Node] to end[Node]
7. For the next query in sortedQuery we select any previously un-selected nodes from sortedTour having indexInTree < Val, and increment their indexInTour in bit and answer the query as done before.
8. Repeating this process for each query we can answer them in O(Qlog(N)).

Below is the C++ implementation of the above approach:

## CPP

 `// C++ program Queries to find the Number of` `// Nodes having Smaller Values from a Given` `// Value in the Subtree of a Node` `#include ` `using` `namespace` `std;` `  `  `// Takes a tree and generates a Euler tour for that` `// tree in 'tour' parameter This is a modified form` `// of DFS in which we push the node while entering for` `// the first time and when exiting from it` `void` `eulerTour(vector >& tree,` `               ``vector<``int``>& vst,` `               ``int` `root,` `               ``vector<``int``>& tour)` `{` `  `  `    ``// Push node in tour while entering` `    ``tour.push_back(root);` `  `  `    ``// DFS` `    ``vst[root] = 1;` `    ``for` `(``auto``& x : tree[root]) {` `        ``if` `(!vst[x]) {` `            ``eulerTour(tree, vst, x, tour);` `        ``}` `    ``}` `  `  `    ``// Push node in tour while exiting` `    ``tour.push_back(root);` `}` `  `  `// Creates the start and end array as described in` `// pre-processing section. Traverse the tour from` `// left to right and update start for 1st occurrence` `// and end for 2nd occurrence of each node` `void` `createStartEnd(vector<``int``>& tour,` `                    ``vector<``int``>& start,` `                    ``vector<``int``>& end)` `{` `    ``for` `(``int` `i = 1; i < tour.size(); ++i) {` `        ``if` `(start[tour[i]] == -1) {` `            ``start[tour[i]] = i;` `        ``}` `        ``else` `{` `            ``end[tour[i]] = i;` `        ``}` `    ``}` `}` `  `  `// Returns a sorted array of pair containing node and` `// tourIndex as described in pre-processing section` `vector >` `createSortedTour(vector<``int``>& tour)` `{` `    ``vector > arr;` `    ``for` `(``int` `i = 1; i < tour.size(); ++i) {` `        ``arr.push_back(make_pair(tour[i], i));` `    ``}` `    ``sort(arr.begin(), arr.end());` `    ``return` `arr;` `}` `  `  `// Binary Indexed Tree Implementation` `// This function will add 1 from the position` `void` `increment(vector<``int``>& bit, ``int` `pos)` `{` `    ``for` `(; pos < bit.size(); pos += pos & -pos) {` `        ``bit[pos]++;` `    ``}` `}` `  `  `// It will give the range sum` `int` `query(vector<``int``>& bit,` `              ``int` `start,` `              ``int` `end)` `{` `    ``--start;` `    ``int` `s1 = 0, s2 = 0;` `    ``for` `(; start > 0; start -= start & -start) {` `        ``s1 += bit[start];` `    ``}` `    ``for` `(; end > 0; end -= end & -end) {` `        ``s2 += bit[end];` `    ``}` `    ``return` `s2 - s1;` `}` ` `  `// Function to calculate the ans for each query` `map, ``int``> cal(``int` `N,` `                                         ``int` `Q,` `                      ``vector> tree,` `            ``vector> queries)` `{` `    ``// Preprocessing` `    ``// Creating the vector to store the tours and queries` `    ``vector<``int``> tour, vst(N + 1, 0),` `        ``start(N + 1, -1),` `        ``end(N + 1, -1),` `        ``bit(2 * N + 4, 0);` `  `  `    ``// For one based indexing in tour.` `    ``// Simplifies code for Binary Indexed Tree.` `    ``// We will ignore the 1st element in tour` `    ``tour.push_back(-1);` `  `  `    ``// Create Euler Tour` `    ``eulerTour(tree, vst, 1, tour);` `  `  `    ``// Create Start and End Array` `    ``createStartEnd(tour, start, end);` `  `  `    ``// Create sortedTour and sortedQuery` `    ``auto` `sortedTour = createSortedTour(tour);` `  `  `    ``auto` `sortedQuery = queries;` `  `  `    ``sort(sortedQuery.begin(), sortedQuery.end());` `  `  `    ``// For storing answers to query` `    ``map, ``int``> queryAns;` `  `  `    ``// We maintain pointers each for sortedTour and` `    ``// sortedQuery.For each element X in sortedTour` `    ``// we first process any queries with val smaller` `    ``// than X's node and update queryptr to first` `    ``// unprocessed query.Then update the position` `    ``// of X in BIT.` `  `  `    ``int` `tourptr = 0, queryptr = 0;` `    ``while` `(queryptr < sortedQuery.size()) {` `  `  `        ``// Queries lies in the range then` `        ``while` `(queryptr < sortedQuery.size()` `               ``&& sortedQuery[queryptr].first` `                      ``<= sortedTour[tourptr].first){` `  `  `            ``auto` `node = sortedQuery[queryptr].second;` `  `  `            ``// Making the query on BIT and dividing by 2.` `            ``queryAns[sortedQuery[queryptr]]` `                ``= query(bit, start[node], end[node]) / 2;` `            ``++queryptr;` `        ``}` `        ``if` `(tourptr < sortedTour.size()) {` `            ``increment(bit, sortedTour[tourptr].second);` `            ``++tourptr;` `        ``}` `    ``}` ` `  `    ``return` `queryAns;` `}` ` `  `// Driver Code` `int` `main()` `{` ` `  `    ``int` `N = 7, Q = 3;` `  `  `    ``// Tree edges` `    ``vector > tree = { {},` `                                      ``{ 4, 6 },` `                                      ``{ 4 },` `                                      ``{ 4 },` `                                      ``{ 1, 2, 3, 5 },` `                                      ``{ 4 },` `                                      ``{ 1, 7 },` `                                      ``{ 6 } };` `  `  `    ``// Queries vector` `    ``vector > queries` `        ``= { make_pair(4, 1),` `            ``make_pair(7, 6),` `            ``make_pair(5, 1) };` `  `  `    ``// Calling the function` `    ``map, ``int``> queryAns = ` `                    ``cal(N, Q, tree, queries);` ` `  `    ``// Print answer in order of input.` `    ``for` `(``auto``& x : queries) {` `        ``cout << queryAns[x] << ``'\n'``;` `    ``}` `  `  `    ``return` `0;` `}`

## Python3

 `# Python3 implementation for the above approach`   `# Import necessary libraries` `from` `typing ``import` `List``, ``Tuple``, ``Dict` `from` `collections ``import` `defaultdict`   `# Recursive function to perform euler tour on the tree` `def` `eulerTour(tree: ``List``[``List``[``int``]], vst: ``List``[``int``], root: ``int``, tour: ``List``[``int``]) ``-``> ``None``:` `  `  `    ``# Append the root to the tour` `    ``tour.append(root)` `    `  `    ``# Mark the root as visited` `    ``vst[root] ``=` `1` `    `  `    ``# Traverse through all the children of the root` `    ``for` `x ``in` `tree[root]:` `      `  `        ``# If a child is not visited, ` `        ``# perform euler tour on that child` `        ``if` `not` `vst[x]:` `            ``eulerTour(tree, vst, x, tour)` `            `  `    ``# Append the root again to ` `    ``# complete the cycle of euler tour` `    ``tour.append(root)`   `# Create start and end index for each node in the euler tour` `def` `createStartEnd(tour: ``List``[``int``], start: ``List``[``int``], end: ``List``[``int``]) ``-``> ``None``:` `  `  `    ``# Traverse through the euler tour and ` `    ``# store the start and end index for each node` `    ``for` `i ``in` `range``(``1``, ``len``(tour)):` `      `  `        ``if` `start[tour[i]] ``=``=` `-``1``:` `            ``start[tour[i]] ``=` `i` `        ``else``:` `            ``end[tour[i]] ``=` `i` `            `  `# Create a sorted euler tour` `def` `createSortedTour(tour: ``List``[``int``]) ``-``> ``List``[``Tuple``[``int``, ``int``]]:` `  `  `    ``# Create a tuple with the node and its index in the euler tour` `    ``arr ``=` `[(tour[i], i) ``for` `i ``in` `range``(``1``, ``len``(tour))]` `    `  `    ``# Sort the array of tuples by the node values` `    ``arr.sort()` `    `  `    ``# Return the sorted array of tuples` `    ``return` `arr` `    `  `# Increment the value of a position in the binary indexed tree` `def` `increment(bit: ``List``[``int``], pos: ``int``) ``-``> ``None``:` `  `  `    ``# Traverse through the binary indexed tree and increment ` `    ``# the value at the given position and its ancestors` `    ``while` `pos < ``len``(bit):` `        ``bit[pos] ``+``=` `1` `        ``pos ``+``=` `pos & ``-``pos`     `def` `query(bit: ``List``[``int``], start: ``int``, end: ``int``) ``-``> ``int``:` `  `  `    ``# Subtract 1 from start position as indexing starts from 0` `    ``start ``-``=` `1` `    ``s1, s2 ``=` `0``, ``0` `    `  `    ``# Calculate sum of BIT from start to root of the tree` `    ``while` `start > ``0``:` `        ``s1 ``+``=` `bit[start]` `        ``start ``-``=` `start & ``-``start` `        `  `    ``# Calculate sum of BIT from end to root of the tree` `    ``while` `end > ``0``:` `        ``s2 ``+``=` `bit[end]` `        ``end ``-``=` `end & ``-``end` `        `  `    ``# Return the difference between s2 and s1` `    ``return` `s2 ``-` `s1`   `def` `cal(N: ``int``, Q: ``int``, tree: ``List``[``List``[``int``]],` `        ``queries: ``List``[``Tuple``[``int``, ``int``]]) ``-``> ``Dict``[``Tuple``[``int``, ``int``], ``int``]:` `  `  `    ``# Initialize variables` `    ``tour, vst, start, end, bit ``=` `[``-``1``], [``0``]``*``(N``+``1``), [``-``1``]``*``(N``+``1``), [``-``1``]``*``(N``+``1``), [``0``]``*``(``2``*``N``+``4``)` `    `  `    ``# Perform Euler tour to create the tour list` `    ``eulerTour(tree, vst, ``1``, tour)` `    `  `    ``# Create start and end arrays` `    ``createStartEnd(tour, start, end)` `    `  `    ``# Sort the tour list based on node values` `    ``sortedTour ``=` `createSortedTour(tour)` `    `  `    ``# Sort the queries list` `    ``sortedQuery ``=` `sorted``(queries)` `    `  `    ``# Initialize a defaultdict to store the query results` `    ``queryAns ``=` `defaultdict(``int``)` `    `  `    ``# Initialize pointers` `    ``tourptr, queryptr ``=` `0``, ``0` `    `  `    ``# Iterate through sortedQuery list` `    ``while` `queryptr < ``len``(sortedQuery):` `      `  `        ``# Iterate through queries whose node values are ` `        ``# less than or equal to the current tour node` `        ``while` `queryptr < ``len``(sortedQuery) ``and` `sortedQuery[queryptr][``0``] <``=` `sortedTour[tourptr][``0``]:` `          `  `            ``# Get the node value from the current query` `            ``node ``=` `sortedQuery[queryptr][``1``]` `            `  `            ``# Calculate and store the query result in queryAns dictionary` `            ``queryAns[sortedQuery[queryptr]] ``=` `query(bit, start[node], end[node]) ``/``/` `2` `            `  `            ``# Increment the query pointer` `            ``queryptr ``+``=` `1` `            `  `        ``# Increment BIT at the position ` `        ``# corresponding to the current tour node` `        ``if` `tourptr < ``len``(sortedTour):` `            ``increment(bit, sortedTour[tourptr][``1``])` `            `  `            ``# Increment the tour pointer` `            ``tourptr ``+``=` `1` `    `  `    ``# Return the queryAns dictionary` `    ``return` `queryAns`     `# Driver Code` `if` `__name__ ``=``=` `"__main__"``:` `    ``import` `math` `  `  `    ``N ``=` `7` `    ``Q ``=` `3` `  `  `    ``# Tree edges` `    ``tree ``=` `{ ``1``: [``4``, ``6``],` `             ``2``: [``4``],` `             ``3``: [``4``],` `             ``4``: [``1``, ``2``, ``3``, ``5``],` `             ``5``: [``4``],` `             ``6``: [``1``, ``7``],` `             ``7``: [``6``] }` `  `  `    ``# Queries vector` `    ``queries ``=` `[(``4``, ``1``), (``7``, ``6``), (``5``, ``1``)]` `  `  `    ``# Calling the function` `    ``queryAns ``=` `cal(N, Q, tree, queries)` ` `  `    ``# Print answer in order of input.` `    ``for` `query ``in` `queries:` `        ``print``(queryAns[query])`   `# This code is contributed by amit_mangal_`

Output:

```3
1
4```

Auxiliary Space: O(Q+N*log(N))

Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!

Previous
Next