// Arup Guha
// 10/7/2019
// Solution 2019 NAQ Problem L: Merchant

import java.util.*;
import java.io.*;

public class l {
	
	final public static int[] OFFSET = {0,1,2,3,2,1,0};
	
	public static int n;
	public static int[][] rawdata;
	public static int[][] forward;
	public static int[][] backward;
	
	public static data[] fData;
	public static data[] bData;
	
	public static void main(String[] args) throws Exception {
	
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(stdin.readLine());
		rawdata = new int[n][2];
		for (int i=0; i<n; i++) {
			StringTokenizer tok = new StringTokenizer(stdin.readLine());
			rawdata[i][0] = Integer.parseInt(tok.nextToken());
			rawdata[i][1] = Integer.parseInt(tok.nextToken());
		}

		// Do this so we can just send a single array to our solve method, for each query.
		fillForward();
		fillBackward();		
		
		// Set up our objects we'll use for each query.
		fData = new data[7];
		for (int i=0; i<7; i++) fData[i] = new data(forward[i]);
		bData = new data[7];
		for (int i=0; i<7; i++) bData[i] = new data(backward[i]);
		
		// Store result here. 
		StringBuffer sb = new StringBuffer();
		
		// Get ready to process queries.
		int numQ = Integer.parseInt(stdin.readLine());
		for (int i=0; i<numQ; i++) {
			
			// Retrieve query.
			StringTokenizer tok = new StringTokenizer(stdin.readLine());
			int s = Integer.parseInt(tok.nextToken())-1;
			int t = Integer.parseInt(tok.nextToken())-1;
			
			// Forward Query.
			if (s < t) sb.append(fData[(7-s%7)%7].query(s,t)+"\n");

			// Backward Query.
			else {
				s = n-1-s;
				t = n-1-t;
				sb.append(bData[(7-s%7)%7].query(s,t)+"\n");
			}
		}
		
		// Output!
		System.out.print(sb);
	}
	
	// forward[i] assumes that we start at index 0 on day i. So forward[1] stores us starting at
	// city 0 on Tuesday, etc.
	public static void fillForward() {
		forward = new int[7][n];
		for (int day=0; day<7; day++) 
			for (int i=0; i<n; i++)
				forward[day][i] = rawdata[i][0]+OFFSET[(day+i)%7]*rawdata[i][1];
	}
	
	// backward[0] is starting on last day 0 and I've flipped days, so last day is first, so we can run the same code to solve the problem.
	public static void fillBackward() {
		backward = new int[7][n];
		for (int day=0; day<7; day++) {
			for (int i=n-1; i>=0; i--) 
				backward[day][i] = rawdata[i][0]+OFFSET[(day-i+n-1)%7]*rawdata[i][1];
			reverse(backward[day]);
		}
	}
	
	public static void reverse(int[] a) {
		for (int i=0; i<a.length/2; i++) {
			int tmp = a[i];
			a[i] = a[a.length-1-i];
			a[a.length-i-1] = tmp;
		}
	}
}

/*** This class is basically a modification of RMQ. ***/
class data {
	
	// Stores the number of terms and levels of our "tree"
	public int n;
	public int levels;
	
	// Store the mins, maxs and maxups (best changes) in all ranges of size 2^k.
	public int[][] mins;
	public int[][] maxs;
	public int[][] maxup;	
	
	public data(int[] list) {
		
		// Go to next power of 2.
		n = 1;
		levels = 1;
		while (n < list.length) {
			n <<= 1;
			levels++;
		}
		
		// Bit more space than I need but makes life easier.
		mins = new int[levels][1<<(levels-1)];
		maxs = new int[levels][1<<(levels-1)];
		maxup = new int[levels][1<<(levels-1)];
		
		// Fill in backwards.
		int skip = 1;
		for (int depth=levels-1; depth>=0; depth--) {
			
			// Special for first row.
			if (depth == levels-1) {
				for (int i=0; i<list.length; i++) {
					mins[depth][i] = maxs[depth][i] = list[i];
					maxup[depth][i] = 0;
				}
				continue;
			}
			
			// Build up for previous levels. For max up, either it's max up from left, or right,
			// OR it could be max of right minus min of left.
			for (int i=0; i< (1<<(levels-1)) - (1<<(levels-1-depth)); i++) {
				mins[depth][i] = Math.min(mins[depth+1][i], mins[depth+1][i+skip]);
				maxs[depth][i] = Math.max(maxs[depth+1][i], maxs[depth+1][i+skip]);
				maxup[depth][i] = Math.max(maxup[depth+1][i], maxup[depth+1][i+skip]);
				maxup[depth][i] = Math.max(maxup[depth][i], maxs[depth+1][i+skip]-mins[depth+1][i]);
			}
			
			// Each level we go up, we have to go to the next power of two for our offset.
			skip <<= 1;
		}
	}
	
	// Returns the result from start to end.
	public int query(int start, int end) {
		
		// Start from index start, and count up.
		int curIdx = start, left = end-start+1;
		int curRes = -1, curMin = -1, curMax = -1;
		
		// Stop when our current index gets past end.
		while (curIdx <= end) {
			
			// Get level of tree we want and how many terms we're adding to our range.
			int myLev = getLevel(left);
			int add = Integer.highestOneBit(left);
			
			// For first update.
			if (curRes == -1) {
				curMin = mins[myLev][curIdx];
				curMax = maxs[myLev][curIdx];
				curRes = maxup[myLev][curIdx];
				curIdx += add;
				left -= add;
			}
			
			// Rest of the updates; building off current running answer, same theory as building the tree.
			else {
				curRes = Math.max(curRes, maxup[myLev][curIdx]);
				curRes = Math.max(curRes, maxs[myLev][curIdx]-curMin);			
				curMin = Math.min(curMin, mins[myLev][curIdx]);
				curMax = Math.max(curMax, maxs[myLev][curIdx]);
				curIdx += add;
				left -= add;
			}
		}
		
		return curRes;
	}
	
	// if pow2 is 1 we want to return n, if pow2 is 2 we want n-1 if pow2 is 2^n we want 0.
	public int getLevel(int pow2) {
		int i = 0;
		while ((1<<i) <= pow2) i++;
		i--;
		return levels-1-i;
	}
}