#!/usr/bin/env python2 import sys # approach: DFS, maintaining an array of stacks. # Stack[i] represents those node values which could end a path of length i with # that label. # # As we descend the tree to each node, put its value onto a stack corresponding # to the longest path that it could end. # # Thus, as the paths get longer the label of the top of the stack gets higher, # and within each stack, the labels increase deeper in the stack. # # Each stack entry stores three things: # - the label # - the multiplicity # - the sum of multiplicities # # This is a first attempt to get a correct method which uses linear search to # find the longest path for each node, and the multiplicities. I had intended # to get this correct and then use bisecting search for both of these, but it # appears that this approach is fast enough for the current data. Maybe better # data can break it. # # With bisecting search, this approach should be O(n log n). MOD = 11092019 DEBUG = 1 < len(sys.argv) def dfs_iterative(tree, label, longest, length, multiplicity): stack = [(0, None)] while stack: u, loc = stack.pop() u_lbl = label[u] if loc is not None: longest[loc].pop() if len(longest[loc]) == 1: longest.pop() else: x = len(longest) while u_lbl < longest[x-1][-1][0]: # FIXME: do a bisect x -= 1 length[u] = x if x == len(longest): longest.append([(-1, 1, 0)]) y = len(longest[x-1]) while 1 < y and longest[x-1][y-1][0] <= u_lbl: # FIXME: do a bisect y -= 1 if y < len(longest[x-1]) - 1: m = (longest[x-1][-1][2] - longest[x-1][y-1][2]) % MOD else: m = longest[x-1][-1][1] multiplicity[u] = m longest[x].append((u_lbl, m, (longest[x][-1][2] + m) % MOD)) stack.append((u, x)) for v in tree[u]: stack.append((v, None)) # read the input n = int(sys.stdin.readline()) label = [int(sys.stdin.readline()) for _ in range(n)] parent = [int(sys.stdin.readline())-1 for _ in range(n-1)] tree = [[] for _ in range(n)] for u, p in enumerate(parent, 1): tree[p].append(u) # list of stacks; one for each possible path length. # longest[i] is a stack which has entries of the form # (label, multiplicity, sum_multiplicity) # representing a path of length i that has the given label and multiplicity. # sum_multiplicity is a sum of all the multiplicities in the stack. longest = [[(-1, 1, 0)]] # sentinel length = [0] * n # the length of the longest path ending at each node multiplicity = [0] * n # number of longest paths ending at each node # base case: root has a path and multiplicity of 1 #dfs(tree, label, longest, 0, length, multiplicity) dfs_iterative(tree, label, longest, length, multiplicity) best = max(length) count = 0 for i, l in enumerate(length): if l == best: count = (count + multiplicity[i]) % MOD print('{} {}'.format(best, count)) if DEBUG: sys.stderr.write('length\n{}\n'.format(length)) sys.stderr.write('multiplicity\n{}\n'.format(multiplicity))