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# (Mono-csc 3.5.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Linq;
using System.Collections.Generic;

namespace Contest
{
  class Program
  {
    static void Main(string[] args)
    {
      Marine2020.D();
    }
    class Marine2020
    {
      public static void A()
      {
        var S = Read.Str();
        Console.WriteLine(S.Substring(0, 3));
      }
      public static void B()
      {
        var A = Read.Long();
        var V = Read.Long();
        var B = Read.Long();
        var W = Read.Long();
        var T = Read.Long();
        var D = Math.Abs(A - B);
        var X = (V - W) * T;
        Console.WriteLine(D <= X ? "YES" : "NO");
      }
      public static void C()
      {
        var N = Read.Int();
        var K = Read.Int();
        var A = Read.IntN();
        var B = new int[N + 1];
        var BNext = new int[N + 1];
        for (int j = 0; j < N; ++j)
        {
          var min = Math.Max(0, j - A[j]);
          var max = Math.Min(N - 1, j + A[j]);
          B[min]++;
          B[max + 1]--;
        }
        if (B[0] == N && B[N] == -N)
        {
          Console.WriteLine(String.Join(" ", Enumerable.Range(0, N).Select(i => N)));
          return;
        }
        for (int i = 0; i < K - 1; ++i)
        {
          var a = 0;
          var BN = new int[N + 1];
          for (int j = 0; j < N; ++j)
          {
            a += B[j];
            var min = Math.Max(0, j - a);
            var max = Math.Min(N - 1, j + a);
            BN[min]++;
            BN[max + 1]--;
          }
          B = BN;
          if (B[0] == N && B[N] == -N)
          {
            Console.WriteLine(String.Join(" ", Enumerable.Range(0, N).Select(i => N)));
            return;
          }
        }
        var ar = 0;
        for(int i = 0; i < N; ++i)
        {
          ar += B[i];
          A[i] = ar;
        }
        Console.WriteLine(String.Join(" ", A));
      }
      public static void D()
      {
        var N = Read.Int();
        var VW = Read.TupleInt(N);
        var Q = Read.Int();
        var VL = Read.TupleInt(Q);
        //var N = 2000;
        //var VW = Enumerable.Range(0, N).Select(i => i <= 511 ? new Tuple<int, int>(1, 1) : new Tuple<int, int>(2, 1)).ToArray();
        //var Q = 20;
        //var VL = Enumerable.Range(0, Q).Select(i => new Tuple<int, int>(2000, i)).ToArray();

        var dp = new Tuple<int[], int[]>[N + 10];
        dp[1] = new Tuple<int[], int[]>(new int[] { 0, VW[0].Item2 }, new int[] { 0, VW[0].Item1 });
        for(int i = 512; i < 1024; ++i)
        {
          if (i > N) { break; }
          dp[i] = new Tuple<int[], int[]>(new int[] { 0, VW[i-1].Item2 }, new int[] { 0, VW[i - 1].Item1 });
        }
        var ans = new List<int>();
        foreach(var vl in VL)
        {
          var V = vl.Item1;
          var L = vl.Item2;
          if (V <= 511)
          {
            DP(VW, dp, V);
            var idx = Bound.Upperbound(dp[V].Item1, L);
            ans.Add(dp[V].Item2[idx - 1]);
          }
          else
          {
            DP(VW, dp, V);
            var VX = V;
            while (VX > 511)
            {
              VX /= 2;
            }
            DP(VW, dp, VX);
            var W1 = dp[VX].Item1;
            var V1 = dp[VX].Item2;
            var W2 = dp[V].Item1;
            var V2 = dp[V].Item2;
            int max = 0;
            for(int i = 0; i < W2.Length; ++i)
            {
              if(W2[i] > L) { break; }
              var idx = Bound.Upperbound(W1, L - W2[i]);
              var value = V1[idx - 1] + V2[i];
              max = Math.Max(max, value);
            }
            ans.Add(max);
          }
        }
        Console.WriteLine(String.Join(Environment.NewLine, ans));
      }
      static void DP(Tuple<int,int>[] VW, Tuple<int[], int[]>[] dp, int v)
      {
        if (dp[v] != null)
        {
          return;
        }
        if (dp[v/2] == null)
        {
          DP(VW, dp, v / 2);
        }
        var prev = dp[v / 2];
        var list = new List<Tuple<int, int>>();
        var len = prev.Item1.Length;
        for (int i=0;i<len;++i)
        {
          list.Add(new Tuple<int, int>(prev.Item1[i], prev.Item2[i]));
          list.Add(new Tuple<int, int>(prev.Item1[i] + VW[v - 1].Item2, prev.Item2[i] + VW[v - 1].Item1));
        }
        list = list.OrderBy(x => x.Item1).ToList();
        var P = -1;
        var W = new List<int>();
        var V = new List<int>();
        for(int i = 0; i < list.Count; ++i)
        {
          if(list[i].Item2 > P)
          {
            W.Add(list[i].Item1);
            V.Add(list[i].Item2);
            P = list[i].Item2;
          }
        }
        dp[v] = new Tuple<int[], int[]>(W.ToArray(), V.ToArray());
      }
    }

    class Util
    {
      public static long[] ASum(long[] array)
      {
        var res = new long[array.Length + 1];
        for (int i = 0; i < array.Length; ++i)
        {
          res[i + 1] = res[i] + array[i];
        }
        return res;
      }
      public static long[,] ASum(long[,] matrix)
      {
        var N = matrix.GetLength(0);
        var M = matrix.GetLength(1);
        var res = new long[N + 1, M + 1];
        for(int i = 0; i < N; ++i)
        {
          for(int j = 0; j < M; ++j)
          {
            res[i + 1, j + 1] = res[i, j + 1] + res[i + 1, j] - res[i, j] + matrix[i, j];
          }
        }
        return res;
      }
      public static Dictionary<T, long> Frequency<T>(T[] array)
      {
        var dict = new Dictionary<T, long>();
        foreach (var a in array)
        {
          if (!dict.ContainsKey(a)) { dict.Add(a, 0); }
          dict[a]++;
        }
        return dict;
      }
    }
    class Bound
    {
      public static int Lowerbound<T1, T2>(SortedList<T1, T2> list, T1 x) where T1 : IComparable<T1>
      {
        return Lowerbound(list.Keys, x);
      }
      public static int Upperbound<T1, T2>(SortedList<T1, T2> list, T1 x) where T1 : IComparable<T1>
      {
        return Upperbound(list.Keys, x);
      }
      public static int Lowerbound<T>(IList<T> list, T x) where T : IComparable<T>
      {
        int min = 0;
        int max = list.Count;
        while (min < max)
        {
          var mid = (min + max) / 2;
          if (list[mid].CompareTo(x) >= 0)
          {
            max = mid;
          }
          else
          {
            min = mid + 1;
          }
        }
        return max;
      }
      public static int Upperbound<T>(IList<T> list, T x) where T : IComparable<T>
      {
        int min = 0;
        int max = list.Count;
        while (min < max)
        {
          var mid = (min + max) / 2;
          if (list[mid].CompareTo(x) > 0)
          {
            max = mid;
          }
          else
          {
            min = mid + 1;
          }
        }
        return max;
      }

    }

    static class Read
{
static Queue<string> queue = new Queue<string>();
static void Enqueue() { var ss = Console.ReadLine().Split(' '); foreach (var s in ss) { queue.Enqueue(s); } }
public static int Int() { if (queue.Count == 0) { Enqueue(); } return Convert.ToInt32(queue.Dequeue()); }
public static long Long() { if (queue.Count == 0) { Enqueue(); } return Convert.ToInt64(queue.Dequeue()); }
public static string Str() { if (queue.Count == 0) { Enqueue(); } return queue.Dequeue(); }
public static int[] IntN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray(); }
public static long[] LongN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray(); }
public static ulong[] ULongN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToUInt64(s)).ToArray(); }
public static string[] StrN() { return Console.ReadLine().Split(' '); }
public static Tuple<int, int>[] TupleInt(int n) { List<Tuple<int, int>> list = new List<Tuple<int, int>>(); for (int i = 0; i < n; ++i) { var ab = Read.IntN(); list.Add(new Tuple<int, int>(ab[0], ab[1])); } return list.ToArray(); }
public static Tuple<long, long>[] TupleLong(int n) { List<Tuple<long, long>> list = new List<Tuple<long, long>>(); for (int i = 0; i < n; ++i) { var ab = Read.LongN(); list.Add(new Tuple<long, long>(ab[0], ab[1])); } return list.ToArray(); }
public static Tuple<string, string>[] TupleStr(int n) { List<Tuple<string, string>> list = new List<Tuple<string, string>>(); for (int i = 0; i < n; ++i) { var ab = Read.StrN(); list.Add(new Tuple<string, string>(ab[0], ab[1])); } return list.ToArray(); }
public static Tuple<double, double>[] TupleDouble(int n) { List<Tuple<double, double>> list = new List<Tuple<double, double>>(); for (int i = 0; i < n; ++i) { var ab = Read.LongN(); list.Add(new Tuple<double, double>(ab[0], ab[1])); } return list.ToArray(); }
public static long[,] LongMatrix(int r, int c) { var mat = new long[r, c]; for (int i = 0; i < r; ++i) { var x = Read.LongN(); for (int j = 0; j < c; ++j) { mat[i, j] = x[j]; } } return mat; }
public static Dictionary<int, HashSet<int>> AdjacencyList(int N, int M, bool isDirectional = false)
{
Dictionary<int, HashSet<int>> dict = new Dictionary<int, HashSet<int>>();
for (int i = 0; i <= N; ++i) { dict.Add(i, new HashSet<int>()); }
        for (int i = 0; i < M; ++i) { var ab = Read.IntN(); if (!dict[ab[0]].Contains(ab[1])) { dict[ab[0]].Add(ab[1]); } if (!isDirectional && !dict[ab[1]].Contains(ab[0])) { dict[ab[1]].Add(ab[0]); } }
        return dict;
}
public static Dictionary<int, Dictionary<int, long>> AdjacencyListWithWeight(int N, int M)
{
Dictionary<int, Dictionary<int, long>> dict = new Dictionary<int, Dictionary<int, long>>(); for (int i = 0; i <= N; ++i) { dict.Add(i, new Dictionary<int, long>()); }
for (int i = 0; i < M; ++i) { var ab = Read.IntN(); dict[ab[0]].Add(ab[1], ab[2]); dict[ab[1]].Add(ab[0], ab[2]); }
return dict;
}
}
    }
}