Queries to find the Minimum Weight from a Subtree of atmost D-distant Nodes from Node X

Given an N-ary Tree rooted at 1, and an array val[] consisting of weights assigned to every node, and a matrix Q[][], consisting of queries of the form {X, D}, the task for each query is to find the minimum of all weights assigned to the nodes which are atmost at a distance D from the node X.

Examples:

Input: Q[][] = {{1, 2}, {2, 1}}, val[] = {1, 2, 3, 3, 5}

           1
          / \
         4   5
        /
       3
      /
     2

Output:
1
3
Explanation:
Query 1: X = 1, D = 2
The nodes atmost at a distance 2 from the node 1 are {1, 3, 4, 5} and the weights assigned to these nodes are {1, 3, 3, 5} respectively.
Therefore, the minimum weight assigned is 1.
Query 2: X = 2, D = 1
The nodes atmost at a distance 1 from node 2 is {2, 3} and the weights assigned to these nodes are {2, 3} respectively.
Therefore, the minimum weight assigned is 2.

Input: Q[][] = {{1, 2}}, val[] = {1, 2, 4}



            1
           / \
          2   3

Output: 1

Naive Approach:
The simplest approach to solve each query is to iterate the tree and find all the nodes which are at most at a distance D from node X and find the minimum of all the weights assigned to these nodes.
Time Complexity: O(Q * N)
Auxiliary Space: O(1)

Efficient Approach:
To optimize the above approach, follow the steps below:

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
  
const int INF = 1e9 + 9;
  
/// Function to perform DFs
void dfs(int a, int par, int dep,
         vector<vector<int> >& v,
         vector<int>& depth, vector<int>& in,
         vector<int>& out,
         vector<pair<int, int> >& inv,
         vector<int>& val, int& tim)
{
  
    // Assign depth
    depth[a] = dep;
  
    // Assign in-time
    in[a] = ++tim;
  
    // Store depth and value to
    // construct Merge Sort Tree
    inv[tim] = make_pair(depth[a], val[a]);
    for (int i : v[a]) {
  
        // Skip the parent
        if (i == par)
            continue;
  
        dfs(i, a, dep + 1, v, depth, in,
            out, inv, val, tim);
    }
  
    // Assign out-time
    out[a] = tim;
}
  
// Function to build the Merge Sort Tree
void build(int node, int l, int r,
           vector<vector<pair<int,
                              int> > >& segtree,
           vector<pair<int, int> >& inv)
{
  
    // If the current node is
    // a leaf node
    if (l == r) {
  
        segtree[node].push_back(inv[l]);
        return;
    }
  
    int mid = (l + r) >> 1;
  
    // Recursively build left and right subtree
    build(2 * node + 1, l, mid, segtree, inv);
    build(2 * node + 2, mid + 1, r, segtree, inv);
  
    // Merge left and right node
    // of merge sort tree
    merge(segtree[2 * node + 1].begin(),
          segtree[2 * node + 1].end(),
          segtree[2 * node + 2].begin(),
          segtree[2 * node + 2].end(),
          back_inserter(segtree[node]));
  
    int mn = INF;
  
    for (auto& i : segtree[node]) {
  
        // Compute the prefix minimum
        mn = min(mn, i.second);
        i.second = mn;
    }
}
  
// Function to solve each query
int query(int x, int y, int dep, int node,
          int l, int r,
          vector<vector<pair<int,
                             int> > >& segtree)
{
    // Check for no overlap
    if (l > y || r < x || x > y)
        return INF;
  
    // Condition for complete overlap
    if (x <= l && r <= y) {
  
        // Find the node with
        // depth greater than d;
        auto it
            = upper_bound(segtree[node].begin(),
                          segtree[node].end(),
                          make_pair(dep, INF));
  
        if (it == segtree[node].begin())
  
            // Return if the first depth
            // is greater than d
            return INF;
  
        // Decrement the pointer;
        it--;
  
        // Return prefix minimum
        return it->second;
    }
    int mid = (l + r) >> 1;
    int a = query(x, y, dep, 2 * node + 1,
                  l, mid, segtree);
  
    int b = query(x, y, dep, 2 * node + 2,
                  mid + 1, r, segtree);
  
    return min(a, b);
}
  
// Function to compute the queries
void answerQueries(vector<pair<int, int> > queries,
                   vector<vector<int> >& v,
                   vector<int> val, int n)
{
    // Stores the time
    int tim = 0;
  
    // Stores the in and out time
    vector<int> in(n + 10), out(n + 10);
  
    // Stores depth
    vector<int> depth(n + 10);
  
    vector<pair<int, int> > inv(n + 10);
    dfs(1, 0, 0, v, depth, in, out, inv, val, tim);
  
    // Merge sort tree to store
    // depth of each node
    vector<vector<pair<int,
                       int> > >
        segtree(4 * n + 10);
  
    // Construct the merge sort tree
    build(0, 1, tim, segtree, inv);
  
    for (auto& i : queries) {
  
        int x = i.first;
        int dep = depth[x] + i.second;
  
        // Find the minimum value in subtree of x
        // and subtree of x lies from in[x]
        // to out[x] in merge sort tree
        int minVal = query(in[x], out[x], dep, 0,
                           1, tim, segtree);
        cout << minVal << endl;
    }
}
  
// Driver Code
int main()
{
  
    /*
                    1
                   /  \
                 4     5
                /
               3
              /
            2
    */
    int n = 5;
  
    // Stores the graph
    vector<vector<int> > v(n + 1);
  
    // Stores the weights
    vector<int> val(n + 1);
  
    // Assign edges
    v[1].push_back(4);
    v[4].push_back(1);
    v[1].push_back(5);
    v[5].push_back(1);
    v[4].push_back(3);
    v[3].push_back(4);
    v[3].push_back(2);
    v[2].push_back(3);
  
    // Assign weights
    val[1] = 1;
    val[2] = 3;
    val[3] = 2;
    val[4] = 3;
    val[5] = 5;
  
    // Stores the queries
    vector<pair<int, int> > queries = { { 1, 2 },
                                        { 2, 1 } };
  
    answerQueries(queries, v, val, n);
    return 0;
}
chevron_right

Output:
1
3

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





Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :