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.
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).
Source: Directi Interview | Set 13
Examples:
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.
Now all the queries can be answered in a constant time.
Graph before dfs1
Graph after dfs1
Below is the required implementation:
C++
// C++ implementation to perform // above operations and queries #include <bits/stdc++.h> using namespace std; /* 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 */ 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 code int 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" ; } } |
Python3
# Python3 implementation to perform # above operations and queries p = [] adj = [ 0 ] * 10000 for 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 dfs2 def 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 Code if __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 |
291 0 0 107 59
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.