#!/usr/bin/env python2 # Key idea: if we know the longest paths and multiplicities of all ancestors of # i, we can efficiently find the longest path and multiplicity that ends at # node i # # Algorithm: # - for each node i (starting at the children of the root and going towards the leaves) # - travel up the parent nodes of i towards the root # - as we go, keep track of the best ancestor of i in terms of path # length and multiplicity # - break early if we have found the best we can do along this # branch -- either because all ancestor paths are shorter, or all # ancestors have labels that are larger # # Runtime: O(n) on many cases, but O(n^2) in the worst case (if we have to walk # all the way to the root repeatedly) import sys MOD = 11092019 # read the input n = int(sys.stdin.readline()) label = [int(sys.stdin.readline()) for _ in range(n)] parent = [-1] + [int(sys.stdin.readline())-1 for _ in range(n-1)] # set up our DP structures longest = [0] * n # aid in breaking early as we walk up towards the root min_label = label[:] # another early break aid 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 length[0] = longest[0] = multiplicity[0] = 1 DEBUG = 1 < len(sys.argv) # now, go over all the children (the tree input is ordered so that all # ancestors of i will have finished before we consider i) for i in range(1, n): ancestor = parent[i] best = i # best ancestor best_mult = 0 # multiplicity of the best ancestor # we can break early if we've already found the longest path we're going to # find along this branch, or there are no further ancestors with compatible # labels while 0 <= ancestor and length[best] <= longest[ancestor] and min_label[ancestor] <= label[i]: if label[ancestor] <= label[i]: if length[best] < length[ancestor]: best = ancestor best_mult = multiplicity[ancestor] elif length[best] == length[ancestor]: best_mult = (best_mult + multiplicity[ancestor]) % MOD ancestor = parent[ancestor] if best != i: # if we found an ancestor which improved things... length[i] = length[best] + 1 multiplicity[i] = best_mult else: # otherwise, we're a singleton path length[i] = multiplicity[i] = 1 longest[i] = max(longest[parent[i]], length[i]) min_label[i] = min(min_label[parent[i]], min_label[i]) 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('count without mod: {}\n'.format(count)) sys.stderr.write('length\n{}\n'.format(length)) sys.stderr.write('multiplicity\n{}\n'.format(multiplicity)) sys.stderr.write('longest\n{}\n'.format(longest))