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 Rust (1.42.0) (judge verdict: Accepted)

fn main() {
	let mut s = String::new();
	use std::io::Read;
	std::io::stdin().read_to_string(&mut s).unwrap();
	let mut s = s.split_whitespace();
	let n: usize = s.next().unwrap().parse().unwrap();
	let mut a = Vec::with_capacity(n + 1);
	for _ in 0..n {
		let v: i32 = s.next().unwrap().parse().unwrap();
		let w: i32 = s.next().unwrap().parse().unwrap();
		a.push((v, w));
	}
	let m = (n + 1).next_power_of_two().trailing_zeros();
	let half = m / 2;
	let mut memo = vec![None; (1 << half) >> 1];
	let q: usize = s.next().unwrap().parse().unwrap();

	let get_ancestors = |v: usize, stop: usize| {
		let mut r = vec![];
		let mut i = v;
		while i > stop {
			r.push(a[i - 1]);
			i /= 2;
		}
		r
	};

	use std::io::Write;
	let out = std::io::stdout();
	let mut out = std::io::BufWriter::new(out.lock());
	for _ in 0..q {
		let v: usize = s.next().unwrap().parse().unwrap();
		let l: i32 = s.next().unwrap().parse().unwrap();
		let depth = (v + 1).next_power_of_two().trailing_zeros();
		let ans = if depth >= half && half > 0 {
			// deep
			let x = v >> (depth - half);
			let memo = if let Some(r) = memo[x - (1 << (half - 1))].as_ref() {
				r
			} else {
				let a = get_ancestors(x, 0);

				let mut r = vec![];
				for i in 0..1 << a.len() {
					let mut v = 0;
					let mut w = 0;
					for j in 0..a.len() {
						if i & (1 << j) != 0 {
							v += a[j].0;
							w += a[j].1;
						}
					}
					r.push((w, v));
				}
				r.sort();
				let mut t = vec![(0, 0)];
				for &r in r[1..].iter() {
					if t.last().unwrap().1 < r.1 {
						t.push(r);
					}
				}
				memo[x - (1 << (half - 1))] = Some(t);
				memo[x - (1 << (half - 1))].as_ref().unwrap()
			};

			if v == x {
				memo[memo.upper_bound_by_key(&l, |a| a.0) - 1].1
			} else {
				let mut b = Vec::with_capacity(1 << (depth - half));
				let a = get_ancestors(v, x);
				for i in 0..1 << a.len() {
					let mut v = 0;
					let mut w = 0;
					for j in 0..a.len() {
						if i & (1 << j) != 0 {
							v += a[j].0;
							w += a[j].1;
						}
					}
					if w <= l {
						b.push((w, v));
					}
				}
				b.sort();
				let mut i = memo.len() - 1;
				let mut ans = 0;
				for (w, v) in b {
					while i > 0 && memo[i].0 + w > l {
						i -= 1;
					}
					if ans < v + memo[i].1 {
						ans = v + memo[i].1;
					}
				}
				ans
			}
		} else {
			// shallow
			let a = get_ancestors(v, 0);
			let mut ans = 0;
			for i in 0..1 << a.len() {
				let mut v = 0;
				let mut w = 0;
				for j in 0..a.len() {
					if i & (1 << j) != 0 {
						v += a[j].0;
						w += a[j].1;
					}
				}
				if w <= l && ans < v {
					ans = v;
				}
			}
			ans
		};
		writeln!(out, "{}", ans).unwrap();
	}
}

pub trait BinarySearch<'a, T: 'a> {
	fn upper_bound_by_key<B, F>(&'a self, b: &B, f: F) -> usize
	where
		B: Ord,
		F: Fn(&'a T) -> B;
}

impl<'a, T: 'a + Ord> BinarySearch<'a, T> for [T] {
	fn upper_bound_by_key<B, F>(&'a self, b: &B, f: F) -> usize
	where
		B: Ord,
		F: Fn(&'a T) -> B,
	{
		let mut first = 0;
		let mut len = self.len() - first;
		while len > 0 {
			let half = len >> 1;
			let mid = first + half;
			use std::cmp::Ordering;
			match f(&self[mid]).cmp(b) {
				Ordering::Less | Ordering::Equal => {
					first = mid + 1;
					len = len - half - 1;
				}
				Ordering::Greater => {
					len = half;
				}
			}
		}
		first
	}
}