#include <bits/stdc++.h>
using namespace std;
// Solve offline queries to find the minimum absolute difference between any two numbers in a subarray
struct Query {
int left;
int right;
int index;
};
constexpr int MAXN = 300000 + 5;
constexpr int BLOCK_SIZE = 400;
constexpr int INF = 1e9;
int nextPos[MAXN]; // Next element in the linked list
int prevPos[MAXN]; // Previous element in the linked list
int compressed[MAXN]; // Compressed original array values
int original[MAXN]; // Original array values
int answer[MAXN]; // Answer for each query
int dp[BLOCK_SIZE + 5][MAXN]; // Precomputed results for short intervals
int blockMin[MAXN]; // Minimum difference for intervals spanning a block
map<int,int> frequencyMap;
vector<Query> queriesByBlock[MAXN / BLOCK_SIZE + 5];
// Comparator: sort queries in descending order of right endpoint
bool compareByRightDesc(const Query &a, const Query &b) {
return a.right > b.right;
}
// Insert position x into the active set and return the minimum neighbor difference
int insertPosition(int x) {
int best = INF;
if (prevPos[x] >= 1) {
best = min(best, original[x] - original[prevPos[x]]);
}
if (nextPos[x] <= MAXN - 1) {
best = min(best, original[nextPos[x]] - original[x]);
}
nextPos[prevPos[x]] = x;
prevPos[nextPos[x]] = x;
return best;
}
// Remove position x from the active set
void removePosition(int x) {
nextPos[prevPos[x]] = nextPos[x];
prevPos[nextPos[x]] = prevPos[x];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
// Read and store original values
for (int i = 1; i <= n; ++i) {
cin >> compressed[i];
original[i] = compressed[i];
}
// Coordinate compression
sort(original + 1, original + n + 1);
original[0] = -INF;
original[n + 1] = INF;
// Assign unique ranks to duplicates
for (int i = 1; i <= n; ++i) {
int rank = lower_bound(original + 1, original + n + 1, compressed[i]) - original;
compressed[i] = rank + (frequencyMap[rank]++);
}
int q;
cin >> q;
// Group queries by block of left endpoint
for (int i = 1; i <= q; ++i) {
int l, r;
cin >> l >> r;
int blockId = (l - 1) / BLOCK_SIZE;
queriesByBlock[blockId].push_back({l, r, i});
}
// Sort queries in each block by decreasing right endpoint
int numBlocks = (n + BLOCK_SIZE - 1) / BLOCK_SIZE;
for (int b = 0; b < numBlocks; ++b) {
sort(queriesByBlock[b].begin(), queriesByBlock[b].end(), compareByRightDesc);
}
// Precompute dp for small intervals (length <= BLOCK_SIZE)
for (int len = 1; len <= min(BLOCK_SIZE, n); ++len) {
for (int start = 1; start + len - 1 <= n; ++start) {
if (len == 1) {
dp[len][start] = INF;
} else {
dp[len][start] = min({
dp[len - 1][start],
dp[len - 1][start + 1],
abs(compressed[start] - compressed[start + len - 1])
});
}
}
}
// Process each block
for (int b = 0; b < numBlocks; ++b) {
int leftBound = b * BLOCK_SIZE + 1;
int rightBound = min(n, (b + 1) * BLOCK_SIZE);
// Initialize linked lists
for (int i = 0; i <= n + 1; ++i) {
prevPos[i] = i - 1;
nextPos[i] = i + 1;
}
// Remove all positions outside [1..rightBound]
for (int i = 1; i < leftBound; ++i) removePosition(compressed[i]);
for (int i = rightBound + 1; i <= n; ++i) removePosition(compressed[i]);
// Build blockMin from rightBound to n
int currentMin = INF;
for (int i = rightBound + 1; i <= n; ++i) {
currentMin = min(currentMin, insertPosition(compressed[i]));
blockMin[i] = currentMin;
}
// Process queries in block b
int ptr = n;
for (auto &query : queriesByBlock[b]) {
int l = query.left;
int r = query.right;
// If interval length is small, use dp table
if (r - l + 1 <= BLOCK_SIZE) {
answer[query.index] = dp[r - l + 1][l];
continue;
}
// Use precomputed blockMin and dynamic insertion
int res = blockMin[r];
// Shrink ptr to r
while (ptr > r) {
removePosition(compressed[ptr--]);
}
// Temporarily remove positions left of leftBound
for (int i = leftBound; i < rightBound; ++i) removePosition(compressed[i]);
// Insert positions from r-1 down to l
int tmpMin = res;
for (int i = rightBound - 1; i >= l; --i) {
tmpMin = min(tmpMin, insertPosition(compressed[i]));
}
res = tmpMin;
// Restore removed positions
for (int i = l - 1; i >= leftBound; --i) insertPosition(compressed[i]);
answer[query.index] = res;
}
}
// Output answers
for (int i = 1; i <= q; ++i) {
cout << answer[i] << "\n";
}
return 0;
}