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 C# (.NET Core 3.1.201) (judge verdict: Accepted)

//#define F
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static Reader;
using static System.Math;
using MethodImplAttribute = System.Runtime.CompilerServices.MethodImplAttribute;
using MethodImplOptions = System.Runtime.CompilerServices.MethodImplOptions;

public static class P
{
    public static void Main()
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var n = NextInt;
        var half = Min(1 << 10, n);
#if F
        var vw = Enumerable.Repeat(0, n).Select(_ => new Obj() { V = 114, W = 514 }).ToArray();
        var q = 100000;
#else
        var vw = Enumerable.Repeat(0, n).Select(_ => new Obj() { V = NextInt, W = NextInt }).ToArray();
        var q = NextInt;
#endif

        int getPInd(int ind) => ((ind + 1) >> 1) - 1;

        //半分全列挙
        int[][] dps = Enumerable.Repeat(0, half).Select(_ => new int[100001]).ToArray();
        dps[0][vw[0].W] = vw[0].V;
        for (int i = 1; i < half; i++)
        {
            var value = vw[i].V;
            var weight = vw[i].W;
            var parent = dps[getPInd(i)];
            for (int j = 100001 - 1; j >= 0; j--)
            {
                dps[i][j] = parent[j];
                if (j + weight < parent.Length) dps[i][j + weight] = Max(dps[i][j + weight], parent[j] + value);
            }
        }

        int[][] accum = Enumerable.Repeat(0, half).Select(_ => new int[100001]).ToArray();
        for (int i = 0; i < half; i++)
        {
            accum[i][0] = dps[i][0];
            for (int j = 1; j < dps[i].Length; j++)
                accum[i][j] = Max(dps[i][j], accum[i][j - 1]);
        }

        List<(int weight, int value)> l1 = new List<(int weight, int value)>(1024);
        List<(int weight, int value)> l2 = new List<(int weight, int value)>(1024);

        for (int _ = 0; _ < q; _++)
        {
#if F
            var ind = n - 1;
            var maxWeight = 13413;
#else
            var ind = NextInt - 1;
            var maxWeight = NextInt;
#endif
            if (ind < half)
            {
                Console.WriteLine(accum[ind][maxWeight]);
                continue;
            }
            List<(int weight, int value)> list = l1;
            var nextList = l2;
            list.Add((0, 0));
            while (ind >= half)
            {
                List<(int weight, int value)> newlist = nextList;

                foreach (var (weight, value) in list)
                {
                    newlist.Add((weight, value));
                    newlist.Add((weight + vw[ind].W, value + vw[ind].V));
                }

                nextList = list;
                nextList.Clear();
                list = newlist;
                ind = getPInd(ind);
            }
            int res = 0;
            foreach (var (weight, value) in list)
            {
                var i = maxWeight - weight;
                if (i < 0 || accum[ind].Length <= i) continue;
                res = Max(res, accum[ind][i] + value);
            }
            list.Clear();
            Console.WriteLine(res);
        }
        Console.Out.Flush();
    }
}

struct Obj
{
    public int V;
    public int W;
}


class SegmentTree<T>
{
    public int Size { get; private set; }
    T Identity;
    T[] Data;
    Func<T, T, T> Merge;
    int LeafCount;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public SegmentTree(int size, T identity, Func<T, T, T> merge)
    {
        Init(size, identity, merge);
        for (int i = 1; i < Data.Length; i++) Data[i] = identity;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public SegmentTree(T[] elems, T identity, Func<T, T, T> merge)
    {
        Init(elems.Length, identity, merge);
        elems.CopyTo(Data, LeafCount);
        for (int i = elems.Length + LeafCount; i < Data.Length; i++) Data[i] = identity;
        for (int i = LeafCount - 1; i >= 1; i--) Data[i] = Merge(Data[i << 1], Data[(i << 1) | 1]);
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private void Init(int size, T identity, Func<T, T, T> merge)
    {
        Size = size;
        Identity = identity;
        Merge = merge;
        LeafCount = 1;
        while (LeafCount < size) LeafCount <<= 1;
        Data = new T[LeafCount << 1];
    }

    public T this[int index]
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get { return Data[LeafCount + index]; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        set { Update(index, value); }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Update(int i, T x) { Data[i += LeafCount] = x; while (0 < (i >>= 1)) Data[i] = Merge(Data[i << 1], Data[(i << 1) | 1]); }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Operate(int i, T x) { Data[i += LeafCount] = Merge(Data[i], x); while (0 < (i >>= 1)) Data[i] = Merge(Data[i << 1], Data[(i << 1) | 1]); }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Query(int l, int r)
    {
        T lRes = Identity, rRes = Identity;
        for (l += LeafCount, r += LeafCount; l <= r; l = (l + 1) >> 1, r = (r - 1) >> 1)
        {
            if ((l & 1) == 1) lRes = Merge(lRes, Data[l]); if ((r & 1) == 0) rRes = Merge(Data[r], rRes);
        }
        return Merge(lRes, rRes);
    }
}


static class Reader
{
    const int BUF_SIZE = 1 << 12;
    static Stream Stream = Console.OpenStandardInput();
    static byte[] Buffer = new byte[BUF_SIZE];
    static int ptr = BUF_SIZE - 1;
    static void Move() { if (++ptr >= Buffer.Length) { Stream.Read(Buffer, 0, BUF_SIZE); ptr = 0; } }

    public static int NextInt
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get
        {
            int res = 0; while (Buffer[ptr] < 48) Move();
            do { res = res * 10 + (int)(Buffer[ptr] ^ 48); Move(); } while (48 <= Buffer[ptr]);
            return res;
        }
    }
}