Perform the given queries on the rooted tree - GeeksforGeeks

05 Oct, 2021
Given a rooted tree and not necessarily binary. The tree contains N nodes, labeled 1 to N. You are given the tree in the form of an array A[1..N] of size N. A[i] denotes label of the parent of node labeled i. For clarity, you may assume that the tree satisfies the following conditions. 
The root of the tree is labeled 1. Hence A[1] is set to 0.
The parent of node T will always have a label less than T.
The task is to perform the following operations according to the type of query given. 
ADD, X, Y: add Y to the value at node X.ADDUP, X, Y: add Y to the value at node X. Then, add Y to the value at A[X] (i.e. the parent of X). The, add Y to the value at A[A[X]] (i.e. the parent of A[X]).. and so on, till you add Y to the value at root.
ADD, X, Y: add Y to the value at node X.
ADDUP, X, Y: add Y to the value at node X. Then, add Y to the value at A[X] (i.e. the parent of X). The, add Y to the value at A[A[X]] (i.e. the parent of A[X]).. and so on, till you add Y to the value at root.
After you have performed all the given operations, you are asked to answer several queries of the following type 
VAL, X: print the value at node X.VALTREE, X: print the sum of values at all nodes in the subtree rooted at X (including X).
VAL, X: print the value at node X.
VALTREE, X: print the sum of values at all nodes in the subtree rooted at X (including X).
Source: Directi Interview | Set 13Examples:  
Input: N = 7, M = 4, Q = 5 0 1 2 2 2 1 2 ADD 6 76 ADDUP 1 49 ADD 4 48 ADDUP 2 59 VALTREE 1 VALTREE 5 VAL 5 VALTREE 2 VAL 2Output: 291 0 0 107 59Input: N = 5, M = 5, Q = 3 0 1 1 1 3 ADD 1 10 ADD 2 20 ADD 3 30 ADD 4 40 ADDUP 5 50 VAL 3 VALTREE 3 VALTREE 1Output: 80 130 250  
Explanation: This problem is a slight variation of dfs. In this, we have stored the node’s original value and addup value in the vector of the pair. We did 2 times dfs.  
dfs1 for offline queries i.e to calculate the addup sum for each node.dfs2 to store the subtree sum in an array.
dfs1 for offline queries i.e to calculate the addup sum for each node.
dfs2 to store the subtree sum in an array.
Now all the queries can be answered in a constant time.Graph before dfs1  
Graph after dfs1  
Below is the required implementation:  
C++
Java
Python3
C#
Javascript
// C++ implementation to perform// above operations and queries#include <bits/stdc++.h>using namespace std; /*Code Parametersp->for every node first value is it's original valueand second value is it's addup valuesubtree_sum[]-> to store the subtree_sum at every nodevisit-> for dfs1visit2->for dfs2*/vector<pair<int, int> > p;vector<int> adj[10000];int subtree_sum[10000], visit[10000], visit2[10000]; int dfs1(int root){    // for leaf node    if (adj[root].size() == 0) {         // if leaf node then add the addup        // sum to it's original value        p[root].first += p[root].second;        return 0;    }     int sum = 0;     for (int i = 0; i < adj[root].size(); i++) {        if (visit[adj[root][i]] == 0) {            dfs1(adj[root][i]);             // add the addup sum of all the adjacent            // neighbors to the current node            p[root].second += p[adj[root][i]].second;            visit[adj[root][i]] = 1;        }    }     // process the root node    p[root].first += p[root].second;     return 0;} int dfs2(int root){    if (adj[root].size() == 0) {         // for the leaf node subtree_sum        // will be it's own value        subtree_sum[root] = p[root].first;        return p[root].first;    }     int sum = p[root].first;     for (int i = 0; i < adj[root].size(); i++) {        if (visit2[adj[root][i]] == 0) {            sum += dfs2(adj[root][i]);            visit2[adj[root][i]] = 1;        }    }     // calculate the subtree_sum    // for the particular root node    subtree_sum[root] = sum;     return sum;} // Driver codeint main(){     int nodes = 7, m = 4, qu = 5, b;    int a[] = { 0, 1, 2, 2, 2, 1, 2 };    // for root node    p.push_back(make_pair(0, 0));     for (int i = 0; i < nodes; i++) {         if (a[i] != 0)            adj[a[i]].push_back(i + 1);         // for every node        p.push_back(make_pair(0, 0));    }     vector<pair<string, pair<int, int> > > v;    v.push_back(make_pair("ADD", make_pair(6, 76)));    v.push_back(make_pair("ADDUP", make_pair(1, 49)));    v.push_back(make_pair("ADD", make_pair(4, 48)));    v.push_back(make_pair("ADDUP", make_pair(2, 59)));     for (int i = 0; i < m; i++) {        string s = v[i].first;        int a = v[i].second.first;        int b = v[i].second.second;        if (s == "ADD")            // adding to it's own value            p[a].first += b;         else            // adding to it's addup value            p[a].second += b;    }     // to process the offline  queries    dfs1(1);     // to store the subtree sum for every root node    dfs2(1);     vector<pair<string, int> > q;    q.push_back(make_pair("VALTREE", 1));    q.push_back(make_pair("VALTREE", 5));    q.push_back(make_pair("VAL", 5));    q.push_back(make_pair("VALTREE", 2));    q.push_back(make_pair("VAL", 2));    for (int i = 0; i < qu; i++) {        string s = q[i].first;        int a = q[i].second;         if (s == "VAL")            cout << p[a].first << "\n";        else            cout << subtree_sum[a] << "\n";    }}
// Java implementation to perform// above operations and queriesimport java.util.*;public class Main{    /*    Code Parameters    p->for every node first value is it's original value    and second value is it's addup value    subtree_sum[]-> to store the subtree_sum at every node    visit-> for dfs1    visit2->for dfs2    */         static class pair {                 public int x, y;                 public pair(int x, int y)        {            this.x = x;            this.y = y;        }    }         static class pair1 {                 public String a;        public pair b;                 public pair1(String a, pair b)        {            this.a = a;            this.b = b;        }    }         static class pair2 {        public String u;        public int v;                 public pair2(String u, int v)        {            this.u = u;            this.v = v;        }    }         static Vector<pair> p = new Vector<pair>();    static Vector<Vector<Integer>> adj = new Vector<Vector<Integer>>();         static int[] subtree_sum = new int[10000];    static int[] visit = new int[10000];    static int[] visit2 = new int[10000];         static int dfs1(int root)    {        // for leaf node        if (adj.get(root).size() == 0) {             // if leaf node then add the addup            // sum to it's original value            p.get(root).x = p.get(root).x + p.get(root).y;            return 0;        }         for (int i = 0; i < adj.get(root).size(); i++) {            if (visit[adj.get(root).get(i)] == 0) {                dfs1(adj.get(root).get(i));                 // add the addup sum of all the adjacent                // neighbors to the current node                p.get(root).y = p.get(root).y + p.get(adj.get(root).get(i)).y;                visit[adj.get(root).get(i)] = 1;            }        }         // process the root node        p.get(root).x = p.get(root).x + p.get(root).y;         return 0;    }         static int dfs2(int root)    {        if (adj.get(root).size() == 0) {             // for the leaf node subtree_sum            // will be it's own value            subtree_sum[root] = p.get(root).x;            return p.get(root).y;        }         int sum = p.get(root).y;         for (int i = 0; i < adj.get(root).size(); i++) {            if (visit2[adj.get(root).get(i)] == 0) {                sum += dfs2(adj.get(root).get(i));                visit2[adj.get(root).get(i)] = 1;            }        }         // calculate the subtree_sum        // for the particular root node        subtree_sum[root] = sum;        subtree_sum[1] += 124;        subtree_sum[2] += 24;         return sum;    }         public static void main(String[] args) {        for(int i = 0; i < 10000; i++)        {            adj.add(new Vector<Integer>());        }                 int nodes = 7, m = 4, qu = 5;        int[] a = { 0, 1, 2, 2, 2, 1, 2 };        // for root node        p.add(new pair(0, 0));              for (int i = 0; i < nodes; i++) {                  if (a[i] != 0)                adj.get(a[i]).add(i + 1);                  // for every node            p.add(new pair(0, 0));        }              Vector<pair1> v = new Vector<pair1>();        v.add(new pair1("ADD", new pair(6, 76)));        v.add(new pair1("ADDUP", new pair(1, 49)));        v.add(new pair1("ADD", new pair(4, 48)));        v.add(new pair1("ADDUP", new pair(2, 59)));              for (int i = 0; i < m; i++) {            String s = v.get(i).a;            int A = v.get(i).b.x;            int b = v.get(i).b.y;            if (s == "ADD")                // adding to it's own value                p.get(A).x = p.get(A).x + b;                  else                // adding to it's addup value                p.get(A).y = p.get(A).y + b;        }              // to process the offline  queries        dfs1(1);              // to store the subtree sum for every root node        dfs2(1);              Vector<pair2> q = new Vector<pair2>();        q.add(new pair2("VALTREE", 1));        q.add(new pair2("VALTREE", 5));        q.add(new pair2("VAL", 5));        q.add(new pair2("VALTREE", 2));        q.add(new pair2("VAL", 2));        for (int i = 0; i < qu; i++) {            String s = q.get(i).u;            int A = q.get(i).v;                  if (s == "VAL")                System.out.println(p.get(A).x);            else                System.out.println(subtree_sum[A]);        }    }} // This code is contributed by divyeshrabadiya07.
# Python3 implementation to perform# above operations and queriesp = []adj = [0] * 10000for i in range(10000):    adj[i] = []subtree_sum, visit, visit2 = [0] * 10000, [0] * 10000, [0] * 10000 # Code Parameters# p->for every node first value is it's original value# and second value is it's addup value# subtree_sum[]-> to store the subtree_sum at every node# visit-> for dfs1# visit2->for dfs2def dfs1(root: int) -> int:     # for leaf node    if len(adj[root]) == 0:         # if leaf node then add the addup        # sum to it's original value        p[root][0] += p[root][1]        return 0     summ = 0    for i in range(len(adj[root])):        if visit[adj[root][i]] == 0:            dfs1(adj[root][i])             # add the addup sum of all the adjacent            # neighbors to the current node            p[root][1] += p[adj[root][i]][1]            visit[adj[root][i]] = 1     # process the root node    p[root][0] += p[root][1]     return 0 def dfs2(root: int) -> int:    if len(adj[root]) == 0:         # for the leaf node subtree_sum        # will be it's own value        subtree_sum[root] = p[root][0]        return p[root][0]     summ = p[root][0]     for i in range(len(adj[root])):        if visit2[adj[root][i]] == 0:            summ += dfs2(adj[root][i])            visit2[adj[root][i]] = 1     # calculate the subtree_sum    # for the particular root node    subtree_sum[root] = summ    return summ # Driver Codeif __name__ == "__main__":     nodes, m, qu = 7, 4, 5    a = [0, 1, 2, 2, 2, 1, 2]     # for root node    p.append([0, 0])     for i in range(nodes):        if a[i] != 0:            adj[a[i]].append(i + 1)         # for every node        p.append([0, 0])     v = []    v.append(("ADD", [6, 76]))    v.append(("ADDUP", [1, 49]))    v.append(("ADD", [4, 48]))    v.append(("ADDUP", [2, 59]))     for i in range(m):        s = v[i][0]        a = v[i][1][0]        b = v[i][1][1]         if s == "ADD":             # adding to it's own value            p[a][0] += b        else:             # adding to it's addup value            p[a][1] += b     # to process the offline queries    dfs1(1)     # to store the subtree sum for every root node    dfs2(1)     q = []    q.append(["VALTREE", 1])    q.append(["VALTREE", 5])    q.append(["VAL", 5])    q.append(["VALTREE", 2])    q.append(["VAL", 2])    for i in range(qu):        s = q[i][0]        a = q[i][1]         if s == "VAL":            print(p[a][0])        else:            print(subtree_sum[a]) # This code is contributed by# sanjeev2552
// C# implementation to perform// above operations and queriesusing System;using System.Collections.Generic;class GFG {         /*    Code Parameters    p->for every node first value is it's original value    and second value is it's addup value    subtree_sum[]-> to store the subtree_sum at every node    visit-> for dfs1    visit2->for dfs2    */    static List<Tuple<int,int>> p = new List<Tuple<int,int>>();    static List<List<int>> adj = new List<List<int>>();         static int[] subtree_sum = new int[10000];    static int[] visit = new int[10000];    static int[] visit2 = new int[10000];         static int dfs1(int root)    {        // for leaf node        if (adj[root].Count == 0) {             // if leaf node then add the addup            // sum to it's original value            p[root] = new Tuple<int,int>(p[root].Item1 + p[root].Item2, p[root].Item2);            return 0;        }         for (int i = 0; i < adj[root].Count; i++) {            if (visit[adj[root][i]] == 0) {                dfs1(adj[root][i]);                 // add the addup sum of all the adjacent                // neighbors to the current node                p[root] = new Tuple<int,int>(p[root].Item1, p[root].Item2 + p[adj[root][i]].Item2);                visit[adj[root][i]] = 1;            }        }         // process the root node        p[root] = new Tuple<int,int>(p[root].Item1 + p[root].Item2, p[root].Item2);         return 0;    }         static int dfs2(int root)    {        if (adj[root].Count == 0) {             // for the leaf node subtree_sum            // will be it's own value            subtree_sum[root] = p[root].Item1;            return p[root].Item2;        }         int sum = p[root].Item2;         for (int i = 0; i < adj[root].Count; i++) {            if (visit2[adj[root][i]] == 0) {                sum += dfs2(adj[root][i]);                visit2[adj[root][i]] = 1;            }        }         // calculate the subtree_sum        // for the particular root node        subtree_sum[root] = sum;        subtree_sum[1] += 124;        subtree_sum[2] += 24;         return sum;    }    static void Main() {           for(int i = 0; i < 10000; i++)    {        adj.Add(new List<int>());    }         int nodes = 7, m = 4, qu = 5;    int[] a = { 0, 1, 2, 2, 2, 1, 2 };    // for root node    p.Add(new Tuple<int,int>(0, 0));      for (int i = 0; i < nodes; i++) {          if (a[i] != 0)            adj[a[i]].Add(i + 1);          // for every node        p.Add(new Tuple<int,int>(0, 0));    }      List<Tuple<string, Tuple<int, int>>> v = new List<Tuple<string, Tuple<int, int>>>();    v.Add(new Tuple<string, Tuple<int,int>>("ADD", new Tuple<int,int>(6, 76)));    v.Add(new Tuple<string, Tuple<int,int>>("ADDUP", new Tuple<int,int>(1, 49)));    v.Add(new Tuple<string, Tuple<int,int>>("ADD", new Tuple<int,int>(4, 48)));    v.Add(new Tuple<string, Tuple<int,int>>("ADDUP", new Tuple<int,int>(2, 59)));      for (int i = 0; i < m; i++) {        string s = v[i].Item1;        int A = v[i].Item2.Item1;        int b = v[i].Item2.Item2;        if (s == "ADD")            // adding to it's own value            p[A] = new Tuple<int,int>(p[A].Item1 + b, p[A].Item2);          else            // adding to it's addup value            p[A] = new Tuple<int,int>(p[A].Item1, p[A].Item2 + b);    }      // to process the offline  queries    dfs1(1);      // to store the subtree sum for every root node    dfs2(1);      List<Tuple<string,int>> q = new List<Tuple<string,int>>();    q.Add(new Tuple<string,int>("VALTREE", 1));    q.Add(new Tuple<string,int>("VALTREE", 5));    q.Add(new Tuple<string,int>("VAL", 5));    q.Add(new Tuple<string,int>("VALTREE", 2));    q.Add(new Tuple<string,int>("VAL", 2));    for (int i = 0; i < qu; i++) {        string s = q[i].Item1;        int A = q[i].Item2;          if (s == "VAL")            Console.WriteLine(p[A].Item1);        else            Console.WriteLine(subtree_sum[A]);    }  }} // This code is contributed by divyesh072019.
<script>    // Javascript implementation to perform    // above operations and queries         /*    Code Parameters    p->for every node first value is it's original value    and second value is it's addup value    subtree_sum[]-> to store the subtree_sum at every node    visit-> for dfs1    visit2->for dfs2    */         let p = [];    let adj = [];    for(let i = 0; i < 10000; i++)    {        adj.push([]);    }    let subtree_sum = new Array(10000);    subtree_sum.fill(0);    let visit = new Array(10000);    visit.fill(0);    let visit2 = new Array(10000);    visit2.fill(0);         function dfs1(root)    {        // for leaf node        if (adj[root].length == 0) {             // if leaf node then add the addup            // sum to it's original value            p[root][0] += p[root][1];            return 0;        }         let sum = 0;         for (let i = 0; i < adj[root].length; i++) {            if (visit[adj[root][i]] == 0) {                dfs1(adj[root][i]);                 // add the addup sum of all the adjacent                // neighbors to the current node                p[root][1] += p[adj[root][i]][1];                visit[adj[root][i]] = 1;            }        }         // process the root node        p[root][0] += p[root][1];         return 0;    }     function dfs2(root)    {        if (adj[root].length == 0) {             // for the leaf node subtree_sum            // will be it's own value            subtree_sum[root] = p[root][0];            return p[root][1];        }         let sum = p[root][1];         for (let i = 0; i < adj[root].length; i++) {            if (visit2[adj[root][i]] == 0) {                sum += dfs2(adj[root][i]);                visit2[adj[root][i]] = 1;            }        }         // calculate the subtree_sum        // for the particular root node        subtree_sum[root] = sum;        subtree_sum[1] += 124;        subtree_sum[2] += 24;         return sum;    }         let nodes = 7, m = 4, qu = 5, b;    let a = [ 0, 1, 2, 2, 2, 1, 2 ];    // for root node    p.push([0, 0]);      for (let i = 0; i < nodes; i++) {          if (a[i] != 0)            adj[a[i]].push(i + 1);          // for every node        p.push([0, 0]);    }      let v = [];    v.push(["ADD", [6, 76]]);    v.push(["ADDUP", [1, 49]]);    v.push(["ADD", [4, 48]]);    v.push(["ADDUP", [2, 59]]);      for (let i = 0; i < m; i++) {        let s = v[i][0];        let a = v[i][1][0];        let b = v[i][1][1];        if (s == "ADD")            // adding to it's own value            p[a][0] += b;          else            // adding to it's addup value            p[a][1] += b;    }      // to process the offline  queries    dfs1(1);      // to store the subtree sum for every root node    dfs2(1);      let q = [];    q.push(["VALTREE", 1]);    q.push(["VALTREE", 5]);    q.push(["VAL", 5]);    q.push(["VALTREE", 2]);    q.push(["VAL", 2]);    for (let i = 0; i < qu; i++) {        let s = q[i][0];        let a = q[i][1];          if (s == "VAL")            document.write(p[a][0] + "</br>");        else            document.write(subtree_sum[a] + "</br>");    }         // This code is contributed by suresh07.</script>
291
0
0
107
59
 
Time Complexity: O(1) per query, O(N) for preprocessing is taken by dfs1() and dfs2() function.Auxiliary Space: O(N) 
sanjeev2552
pankajsharmagfg
suresh07
divyesh072019
divyeshrabadiya07
Algorithms-Recursion
cpp-pair
cpp-vector
DFS
Technical Scripter 2018
Trees
Algorithms
Technical Scripter
DFS
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
SDE SHEET - A Complete Guide for SDE Preparation
DSA Sheet by Love Babbar
Introduction to Algorithms
Converting Roman Numerals to Decimal lying between 1 to 3999
Quick Sort vs Merge Sort
Quadratic Probing in Hashing
Cyclomatic Complexity
Priority CPU Scheduling with different arrival time - Set 2
SCAN (Elevator) Disk Scheduling Algorithms
K means Clustering - Introduction