#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 2^19 is enough for N = 400,000
const int LOG = 19;
void solve() {
int n;
if (!(cin >> n)) return;
vector<long long> p(n + 1, 0);
vector<long long> coords;
coords.push_back(0);
for (int i = 1; i <= n; i++) {
long long val;
cin >> val;
p[i] = p[i - 1] + val;
coords.push_back(p[i]);
}
// Coordinate compression for fast prefix sum lookup
sort(coords.begin(), coords.end());
coords.erase(unique(coords.begin(), coords.end()), coords.end());
auto get_id = [&](long long x) {
return lower_bound(coords.begin(), coords.end(), x) - coords.begin();
};
// next_occ[i] = smallest j > i such that p[j] == p[i]
vector<int> next_occ(n + 1, n + 1);
vector<int> last_seen(coords.size(), -1);
for (int i = n; i >= 0; i--) {
int id = get_id(p[i]);
if (last_seen[id] != -1) {
next_occ[i] = last_seen[id];
}
last_seen[id] = i;
}
// min_end[i] = minimum end-index of any zero-sum subarray fully contained in [i, n]
vector<int> min_end(n + 2, n + 1);
for (int i = n; i >= 1; i--) {
min_end[i] = min_end[i + 1];
// Subarray starting at index i ends at next_occ[i-1]
if (next_occ[i - 1] <= n) {
min_end[i] = min(min_end[i], next_occ[i - 1]);
}
}
// Binary Lifting table
// up[0][i] is the next available starting position after one sum-0 subarray
vector<vector<int>> up(LOG, vector<int>(n + 2, n + 1));
for (int i = 1; i <= n; i++) {
if (min_end[i] <= n) {
up[0][i] = min_end[i] + 1;
} else {
up[0][i] = n + 1;
}
}
// Build the sparse table
for (int k = 1; k < LOG; k++) {
for (int i = 1; i <= n + 1; i++) {
up[k][i] = up[k - 1][up[k - 1][i]];
}
}
int q;
cin >> q;
while (q--) {
int l, r;
cin >> l >> r;
int count = 0;
int curr = l;
// Binary jump through disjoint subarrays
for (int k = LOG - 1; k >= 0; k--) {
// If the jump stays within the query boundary r
if (up[k][curr] <= r + 1) {
count += (1 << k);
curr = up[k][curr];
}
}
cout << count << "\n";
}
}
int main() {
// Fast I/O is critical for 400k constraints
ios::sync_with_stdio(false);
cin.tie(NULL);
solve();
return 0;
}