Given a tree with N vertices from 0 to N - 1 (0th node is root) and val[] where val[i] denotes the value of the ith vertex, the task is to find the array of integers ans[] of length N, where ans[i] denotes the median value of all its ancestors' values including ith vertex.
Points to remember:
If number of nodes are even: then median = ((n/2th node + ((n)/2th+1) node) /2
If the number of nodes is odd: then median = (n+1)/2th node.
Approach: The problem can be solved based on the following idea:
Use DFS traversal from root to all nodes in top-down manner and use multisets(s, g) to store the smaller and the greater values from effective median of all the ancestors for a node.
Follow the steps mentioned below to implement the idea:
Use a top-down DFS to traverse from the root to all the nodes.
Create multiset s to store values less than the effective median and multiset g for greater values.
Whenever entering a node, before calling DFS on its children, insert the value of that node in s or g accordingly such that the size of s and g are differed utmost by 1.
Whenever we exit the node, remove the value of that node from s or g.
Use a map ans[] to store the required answer for each node.
If the size of g and s are equal then ans[node] would be the last element of s.
Otherwise, ans[node] would store the first element of g.
Below is the implementation of the above approach:
C++
// C++ code to implement the approach#include<bits/stdc++.h>usingnamespacestd;// Map to store final ans for each nodeunordered_map<int,float>ans;// MultiSets s and g to store smaller and// greater values than effective medianmultiset<int>s,g;// Function to add an edge// between nodes u and vvoidaddEdge(vector<int>adj[],intu,intv){adj[u].push_back(v);adj[v].push_back(u);}// insert v either in s or gvoidhelper(intv){s.insert(v);autols=(--s.end());inttemp=*ls;s.erase(ls);g.insert(temp);if(g.size()>s.size()){temp=*(g.begin());g.erase(g.begin());s.insert(temp);}}// Median of AncestorsvoidMedianOfAncestors(vector<int>adj[],intnode,vector<int>&vis,vector<int>&val){intv=val[node];vis[node]=1;// insert v into multisetshelper(v);if(g.size()!=s.size())ans[node]=*(--s.end());elseans[node]=((*(--s.end()))*1.0+(*(g.begin()))*1.0)/2;for(autochild:adj[node]){if(vis[child]==0)MedianOfAncestors(adj,child,vis,val);}// remove v from multisetsif(s.find(v)!=s.end())s.erase(s.find(v));elseg.erase(g.find(v));}// Driver Codeintmain(){// Number of nodes in a treeintN=9;// Initialize treevector<int>adj[N];// Tree FormationaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,3);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,2,6);addEdge(adj,2,7);addEdge(adj,2,8);// Values of nodes of treevector<int>val={3,4,2,3,6,2,10,8,1};vector<int>vis(N,0);// Function callMedianOfAncestors(adj,0,vis,val);for(inti=0;i<N;i++)cout<<ans[i]<<" ";cout<<endl;return0;}
Java
// Java equivalentimportjava.util.*;classMain{// Map to store final ans for each nodestaticHashMap<Integer,Float>ans=newHashMap<>();// MultiSets s and g to store smaller and// greater values than effective medianstaticTreeSet<Integer>s=newTreeSet<>();staticTreeSet<Integer>g=newTreeSet<>();// Function to add an edge// between nodes u and vstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}// insert v either in s or gstaticvoidhelper(intv){s.add(v);inttemp=s.last();s.remove(temp);g.add(temp);if(g.size()>s.size()){temp=g.first();g.remove(temp);s.add(temp);}}// Median of AncestorsstaticvoidMedianOfAncestors(ArrayList<ArrayList<Integer>>adj,intnode,ArrayList<Integer>vis,ArrayList<Integer>val){intv=val.get(node);vis.set(node,1);// insert v into multisetshelper(v);if(g.size()!=s.size())ans.put(node,(float)s.last());elseans.put(node,((float)s.last()+(float)g.first())/2);for(intchild:adj.get(node)){if(vis.get(child)==0)MedianOfAncestors(adj,child,vis,val);}// remove v from multisetsif(s.contains(v))s.remove(v);elseg.remove(v);}// Driver Codepublicstaticvoidmain(String[]args){// Number of nodes in a treeintN=9;// Initialize treeArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<N;i++)adj.add(newArrayList<>());// Tree FormationaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,3);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,2,6);addEdge(adj,2,7);addEdge(adj,2,8);// Values of nodes of treeArrayList<Integer>val=newArrayList<>(Arrays.asList(3,4,2,3,6,2,10,8,1));ArrayList<Integer>vis=newArrayList<>(Collections.nCopies(N,0));// Function callMedianOfAncestors(adj,0,vis,val);for(inti=0;i<N;i++)System.out.print(ans.get(i)+" ");System.out.println();}}
Python3
# Python code to implement the approachfromcollectionsimportdefaultdictimportheapq# Map to store final ans for each nodeans=defaultdict(float)# Heaps s and g to store smaller and# greater values than effective medians=[]g=[]# Function to add an edge# between nodes u and vdefaddEdge(adj,u,v):adj[u].append(v)adj[v].append(u)# insert v either in s or gdefhelper(v):s.append(-v)heapq.heapify(s)temp=-heapq.heappop(s)heapq.heappush(g,temp)iflen(g)>len(s):temp=heapq.heappop(g)heapq.heappush(s,-temp)# Median of AncestorsdefMedianOfAncestors(adj,node,vis,val):v=val[node]vis[node]=1# insert v into heapshelper(v)iflen(g)!=len(s):ans[node]=-s[0]else:ans[node]=(g[0]+-s[0])/2forchildinadj[node]:ifnotvis[child]:MedianOfAncestors(adj,child,vis,val)# remove v from heapsif-vins:s.remove(-v)heapq.heapify(s)else:g.remove(v)heapq.heapify(g)# Driver Code# Number of nodes in a treeN=9# Initialize treeadj=defaultdict(list)# Tree FormationaddEdge(adj,0,1)addEdge(adj,0,2)addEdge(adj,1,3)addEdge(adj,1,4)addEdge(adj,1,5)addEdge(adj,2,6)addEdge(adj,2,7)addEdge(adj,2,8)# Values of nodes of treeval=[3,4,2,3,6,2,10,8,1]vis=[0]*N# Function callMedianOfAncestors(adj,0,vis,val)foriinrange(N):print(ans[i],end=" ")print()# This Code is contributed by Prasad Kandekar(prasad264)
JavaScript
// Importing packages is not necessary in JavaScript// Map to store final ans for each nodeconstans=newMap();// MultiSets s and g to store smaller and greater values than effective medianconsts=newSet();constg=newSet();// Function to add an edge between nodes u and vfunctionaddEdge(adj,u,v){adj[u].push(v);adj[v].push(u);}// insert v either in s or gfunctionhelper(v){s.add(v);lettemp=[...s].pop();s.delete(temp);g.add(temp);if(g.size>s.size){temp=[...g][0];g.delete(temp);s.add(temp);}}// Median of AncestorsfunctionMedianOfAncestors(adj,node,vis,val){letv=val[node];vis[node]=1;// insert v into multisetshelper(v);if(g.size!==s.size)ans.set(node,s.values().next().value);elseans.set(node,(s.values().next().value+[...g][0])/2);for(letchildofadj[node]){if(vis[child]===0)MedianOfAncestors(adj,child,vis,val);}// remove v from multisetsif(s.has(v))s.delete(v);elseg.delete(v);}// Driver Code// Number of nodes in a treeconstN=9;// Initialize treeconstadj=newArray(N).fill().map(()=>[]);// Tree FormationaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,3);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,2,6);addEdge(adj,2,7);addEdge(adj,2,8);// Values of nodes of treeconstval=[3,4,2,3,6,2,10,8,1];constvis=newArray(N).fill(0);// Function callMedianOfAncestors(adj,0,vis,val);for(leti=0;i<N;i++)console.log(ans.get(i)+" ");
C#
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;classMedianOfAncestors{staticDictionary<int,double>ans=newDictionary<int,double>();// Dictionary to store the final// answer for each nodestaticList<double>s=newList<double>();// List to store values// smaller than the effective// medianstaticList<double>g=newList<double>();// List to store values// greater than the effective// medianstaticvoidaddEdge(Dictionary<int,List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}// Insert v either in s or gstaticvoidHelper(doublev){s.Add(-v);// Add the negation of v to ss.Sort();// Sort s in non-increasing orderdoubletemp=-s[0];// Get the largest value in ss.RemoveAt(0);// Remove the largest value from sg.Add(temp);// Add the largest value to gg.Sort();// Sort g in non-decreasing orderif(g.Count>s.Count)// If g has more elements than s,// move an element from g to s{temp=g[0];// Get the smallest value in gg.RemoveAt(0);// Remove the smallest value from gs.Add(-temp);// Add the negation of the// smallest value to ss.Sort();// Sort s in non-increasing order}}// Depth First Search function to traverse the tree and// compute the effective median of ancestors for each// nodestaticvoidDFS(Dictionary<int,List<int>>adj,intnode,bool[]vis,int[]val){doublev=val[node];// Value of the current nodevis[node]=true;// Mark the current node as visitedHelper(v);// Insert v either in s or gif(g.Count!=s.Count)// If g has more elements than s,// the effective median is the// largest element in s{ans[node]=-s[0];// Store the effective median// for the current node}else// Otherwise, the effective median is the// average of the smallest element in g and the// largest element in s{ans[node]=(g[0]+-s[0])/2;// Store the effective median// for the current node}foreach(intchildinadj[node])// Traverse the children// of the current node{if(!vis[child])// If the child has not been// visited yet, visit it{DFS(adj,child,vis,val);}}if(s.Contains(-v))// If the negation of v is in s,// remove it from s{s.Remove(-v);}else// Otherwise, remove v from g{g.Remove(v);}}staticvoidMain(string[]args){intN=9;// Number of nodes in the treeDictionary<int,List<int>>adj=newDictionary<int,List<int>>();// Dictionary to store the// adjacency list of the treefor(inti=0;i<N;i++){adj[i]=newList<int>();}addEdge(adj,0,1);// Add edges to the treeaddEdge(adj,0,2);addEdge(adj,1,3);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,2,6);addEdge(adj,2,7);addEdge(adj,2,8);int[]val=newint[]{3,4,2,3,6,2,10,8,1};bool[]vis=newbool[N];DFS(adj,0,vis,val);for(inti=0;i<N;i++){Console.Write(ans[i]+" ");}Console.WriteLine();}}// This Code is contributed by Vikram_Shirsat
Output
3 3.5 2.5 3 4 3 3 3 2
Time Complexity: O(N * log(N)) Auxiliary Space: O(N)