Problem:
Score : 700 points

Problem Statement

We have a rooted binary tree with N vertices, where the vertices are numbered 1 to N.
Vertex 1 is the root, and the parent of Vertex i (i \geq 2) is Vertex \left[ \frac{i}{2} \right].

Each vertex has one item in it. The item in Vertex i has a value of V_i and a weight of W_i.
Now, process the following query Q times:

Given are a vertex v of the tree and a positive integer L.
Let us choose some (possibly none) of the items in v and the ancestors of v so that their total weight is at most L.
Find the maximum possible total value of the chosen items.

Here, Vertex u is said to be an ancestor of Vertex v when u is an indirect parent of v, that is, there exists a sequence of vertices w_1,w_2,\ldots,w_k (k\geq 2) where w_1=v, w_k=u, and w_{i+1} is the parent of w_i for each i.

Constraints

All values in input are integers.

1 \leq N < 2^{18}

1 \leq Q \leq 10^5

1 \leq V_i \leq 10^5

1 \leq W_i \leq 10^5

For the values v and L given in each query, 1 \leq v \leq N and 1 \leq L \leq 10^5.

Input

Let v_i and L_i be the values v and L given in the i-th query.
Then, Input is given from Standard Input in the following format:

N
V_1 W_1
:
V_N W_N
Q
v_1 L_1
:
v_Q L_Q

Output

For each integer i from 1 through Q,
the i-th line should contain the response to the i-th query.

Sample Input 1

3
1 2
2 3
3 4
3
1 1
2 5
3 5

Sample Output 1

0
3
3

In the first query, we are given only one choice: the item with (V, W)=(1,2). Since L = 1, we cannot actually choose it, so our response should be 0.

In the second query, we are given two choices: the items with (V, W)=(1,2) and (V, W)=(2,3). Since L = 5, we can choose both of them, so our response should be 3.

Sample Input 2

15
123 119
129 120
132 112
126 109
118 103
115 109
102 100
130 120
105 105
132 115
104 102
107 107
127 116
121 104
121 115
8
8 234
9 244
10 226
11 227
12 240
13 237
14 206
15 227

Sample Output 2

256
255
250
247
255
259
223
253

Solution in Kotlin (1.3.71) (judge verdict: Accepted)

@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")

import java.io.PrintWriter
import kotlin.math.*
import kotlin.random.Random
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
    val numCases = 1//readInt()
    case@ for(case in 1..numCases) {
        //print("Case #$case: ")

        val n = readInt()

        val V = IntArray(n+1)
        val W = IntArray(n+1)

        for(i in 1..n) {
            V[i] = readInt()
            W[i] = readInt()
        }

        val k = n.bitLength
        val h = (k+1)/2
        val m = (1 shl h) - 1

        val D = Array(m+1) { IntArray(maxL+1) }

        for(i in 1..m) {
            val p = i shr 1
            D[p].copyInto(D[i])
            for(j in W[i]..maxL) {
                D[i].setMax(j, D[p][j-W[i]] + V[i])
            }
        }

        val q = readInt()

        repeat(q) {
            var v = readInt()
            val l = readInt()

            val sz = 1 shl max(v.bitLength - h, 0)
            var csz = 1

            val vs = IntArray(sz)
            val ws = IntArray(sz)

            var ans = 0

            while(v > m) {
                for(i in 0 until csz) {
                    vs[csz + i] = vs[i] + V[v]
                    ws[csz + i] = ws[i] + W[v]
                }

                csz = csz shl 1
                v = v shr 1
            }

            for(i in vs.indices) {
                if(ws[i] <= l) ans = max(ans, D[v][l-ws[i]] + vs[i])
            }

            println(ans)
        }
    }
}

const val maxL = 1e5.toInt()

inline val Int.clz get() = Integer.numberOfLeadingZeros(this)
inline val Long.clz get() = java.lang.Long.numberOfLeadingZeros(this)
inline val Int.ctz get() = Integer.numberOfTrailingZeros(this)
inline val Long.ctz get() = java.lang.Long.numberOfTrailingZeros(this)
val Int.bitLength get() = 32 - clz
val Long.bitLength get() = 64 - clz

fun IntArray.setMax(i: Int, v: Int) = if(v > get(i)) { set(i, v); true } else false

class IntList(initialCapacity: Int = 12) {
    private var _arr = IntArray(initialCapacity)
    private val capacity get() = _arr.size
    var size = 0
        private set
    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size

    constructor(copyFrom: IntArray): this(copyFrom.size) { copyFrom.copyInto(_arr); size = copyFrom.size }
    constructor(copyFrom: Collection<Int>): this(copyFrom.size) { _arr = copyFrom.toIntArray(); size = copyFrom.size }

    fun contentEquals(other: IntList): Boolean {
        return this === other || size == other.size && indices.all { this[it] == other[it] }
    }

    private fun grow(minCapacity: Int = 8) {
        val newCapacity = maxOf(minCapacity, capacity + (capacity shr 1))
        _arr = _arr.copyOf(newCapacity)
    }

    fun ensureCapacity(minCapacity: Int) { if(capacity < minCapacity) grow(minCapacity) }

    operator fun get(index: Int): Int {
        require(index in 0 until size)
        return _arr[index]
    }

    operator fun set(index: Int, value: Int) {
        require(index in 0 until size)
        _arr[index] = value
    }

    fun add(value: Int) {
        if(size == capacity) grow()
        _arr[size++] = value
    }

    fun add(index: Int, element: Int) {
        if(size == capacity) grow()
        _arr.copyInto(_arr, index + 1, index, size)
        size++
        set(index, element)
    }

    fun clear() { size = 0 }

    fun removeAt(index: Int): Int {
        val e = get(index)
        _arr.copyInto(_arr, index, index + 1, size)
        size--
        return e
    }

    operator fun iterator() = object: IntIterator() {
        private var pos = 0
        override fun hasNext() = pos < size
        override fun nextInt() = get(pos++)
    }

    inline fun isEmpty() = size == 0
    inline fun isNotEmpty() = size != 0

    fun pop() = _arr[--size]

    fun swap(i: Int, j: Int) { val t = this[i]; this[i] = this[j]; this[j] = t }
    fun reverse() {
        for(i in 0 until size / 2) swap(i, lastIndex - i)
    }

    fun shuffle(rnd: Random = random) = _shuffle(rnd, _arr::get, _arr::set, size)
    fun sort() { shuffle(); _arr._sort(0, size) }
    fun sortDescending() { sort(); reverse() }

    fun joinToString(separator: CharSequence) = if(size == 0) "" else let {
        buildString {
            append(it[0])
            for (i in 1 until size) {
                append(separator).append(it[i])
            }
        }
    }

    override fun toString() = "[" + joinToString(", ") + "]"

    fun toIntArray() = _arr.copyOf(size)
    fun toList() = List(size, ::get)

    inline fun first() = get(0)
    inline fun last() = get(lastIndex)
}

inline fun IntList(size: Int, init: (Int) -> Int) = IntList(size).apply {
    for(i in 0 until size) { add(init(i)) }
}
inline fun IntArray.toIntList() = IntList(this)
inline fun Collection<Int>.toIntList() = IntList(this)
inline fun intListOf(vararg values: Int) = IntList(values)

fun IntList.max() = (1 until size).fold(this[0]) { acc, i -> max(acc, this[i]) }
fun IntList.min() = (1 until size).fold(this[0]) { acc, i -> min(acc, this[i]) }
fun IntList.getOrNull(i: Int) = if(i in indices) get(i) else null
inline fun IntList.count(predicate: (Int) -> Boolean) = indices.count { predicate(this[it]) }
fun IntList.copyOf() = IntList(size, ::get)

/** IO */
//@JvmField val INPUT = File("input.txt").inputStream()
//@JvmField val OUTPUT = File("output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar()
        else c
    }
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(true) {
            when(c) {
                '\n', Char.MIN_VALUE -> return@buildString
                else -> {
                    append(c)
                    c = readChar()
                }
            }
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/** shuffles and sort overrides to avoid quicksort attacks */
private inline fun <T> _shuffle(rnd: Random, get: (Int) -> T, set: (Int, T) -> Unit, size: Int) {
    // Fisher-Yates shuffle algorithm
    for (i in size - 1 downTo 1) {
        val j = rnd.nextInt(i + 1)
        val temp = get(i)
        set(i, get(j))
        set(j, temp)
    }
}

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

fun IntArray.shuffle(rnd: Random = random) = _shuffle(rnd, ::get, ::set, size)
fun IntArray.sort() { shuffle(); _sort() }
fun IntArray.sortDescending() { shuffle(); _sortDescending() }

fun LongArray.shuffle(rnd: Random = random) = _shuffle(rnd, ::get, ::set, size)
fun LongArray.sort() { shuffle(); _sort() }
fun LongArray.sortDescending() { shuffle(); _sortDescending() }

fun DoubleArray.shuffle(rnd: Random = random) = _shuffle(rnd, ::get, ::set, size)
fun DoubleArray.sort() { shuffle(); _sort() }
fun DoubleArray.sortDescending() { shuffle(); _sortDescending() }

fun CharArray.shuffle(rnd: Random = random) = _shuffle(rnd, ::get, ::set, size)
inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T: Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T: Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T: Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T: Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

fun `please stop removing these imports IntelliJ`() { iprintln(max(1, 2)) }

/** additional commons */
inline fun <T> Iterable<T>.sumByLong(func: (T) -> Long) = fold(0L) { acc, t -> acc + func(t) }
inline fun <T> Sequence<T>.sumByLong(func: (T) -> Long) = fold(0L) { acc, t -> acc + func(t) }
inline fun <T> Array<T>.sumByLong(func: (T) -> Long) = fold(0L) { acc, t -> acc + func(t) }
fun IntArray.sumLong() = fold(0L, Long::plus)