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 2
Output:
291
0
0
107
59
Input:
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 1
Output:
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++ 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" ;
}
} |
// Java implementation to perform // above operations and queries import 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 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 |
// C# implementation to perform // above operations and queries using 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)