fun main() { val testCase = readln().toInt() for (case in 1 .. testCase) { val (n, k) = readln().split(' ').map(String::toInt) val average = readln().split(' ').map(String::toInt) val parent = readln().split(' ').map{it.toInt() - 1} val result = solve(n, k.toLong(), average, parent) println("Case #$case: $result") } } inline fun List.partitionPoint(predicate: (Int) -> Boolean): Int { var min = 0 var max = size while (min < max) { val mid = (min + max) shr 1 if (predicate(this[mid])) { max = mid }else { min = mid + 1 } } return max } class Bit(val size: Int) { private val vec = IntArray(size){0} fun get(position: Int): Int { var pos = position var result = 0 while (0 <= pos) { result += vec[pos] pos -= pos.inv() and (pos + 1) } return result } fun add(position: Int, value: Int) { var pos = position while (pos < size) { vec[pos] += value pos += pos.inv() and (pos + 1) } } } fun solve(n: Int, k: Long, average: List, parent: List): Long { val graph = Array(n){ mutableListOf() } for (i in parent.indices) { graph[parent[i]].add(i + 1) } val stack = ArrayDeque(listOf(0)) val lowerCountInSubTree = IntArray(n){0} val scores = average.sorted() val bit = Bit(n) while (stack.isNotEmpty()) { val top = stack.removeLast() if (top >= 0) { stack.add(-1 - top) val score = average[top] val pos = scores.partitionPoint { it >= score } bit.add(pos, 1) val lowerPos = scores.partitionPoint { it * k >= score } lowerCountInSubTree[top] = bit.get(lowerPos - 1) for (child in graph[top]) { stack.add(child) } }else { val node = -1 - top val score = average[node] val lowerPos = scores.partitionPoint { it * k >= score } val current = bit.get(lowerPos - 1) val prev = lowerCountInSubTree[node] lowerCountInSubTree[node] = current - prev } } var result = 0L for (node in 0 until n) { val score = average[node] val lowerPos = scores.partitionPoint { it * k >= score } val outer = bit.get(lowerPos - 1) - lowerCountInSubTree[node] result += outer.toLong() * lowerCountInSubTree[node] } return result }