/*
莫队算法是离线算法,用来解决已知l,r问你l,r里面值的问题
对块进行排序,后面的块通过前面的块左移右移得到,所以可能有的情况能得到O(1)或者较低的复杂度
排序的时候除以跟好n(?)
本题题意:从l到r区间内问有多少个不同的数,询问很多
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#include<vector>
using namespace std;
const int MAX = 2000000 + 10;
int a[MAX];
map <int, int> table;
int res[MAX];
int ans[MAX];
int n, m;
vector<int> G[MAX];
int unit;
struct edge{
int l, r, id;
}b[MAX];
bool cmp(edge i, edge j){
if(i.l/unit == j.l/unit){
return i.r/unit < j.r/unit;
}
return i.l/unit < j.l/unit;
}
void modui()
{
sort(b + 1, b + m + 1, cmp);
memset(res, 0, sizeof(res));
int l = 1, r = 0, ret = 0;
for(int i = 1; i <= m; i++){
while(l < b[i].l){
res[a[l]] --;
if(res[a[l]] == 0)
ret--;
l++;
}//l不是,那么数少一,如果该数目变成0,说明原来加了该数,总数减少1
while(l > b[i].l){
res[a[--l]]++;
if(res[a[l]] == 1)
ret++;
}//l是,那么l-1也是(l>b[i].l)说明l少1可能就是临界值,如果变成1,说明多了一个数
while( r < b[i].r){
res[a[++r]]++;
if(res[a[r]] == 1)
ret++;
}
while( r > b[i].r){
res[a[r]] --;
if(res[a[r]] == 0)
ret--;
r--;
}
ans[b[i].id] = ret;
//块的编号
}
for(int i = 1; i <= m ; i++)
printf("%d\n",ans[i]);
}
int main()
{
freopen ("data.in", "r", stdin);
freopen ("data.out", "w", stdout);
while(~scanf("%d", &n)){
int num = 0;
table.clear();
for(int i = 1; i <= n ; i++)
G[i].clear();
for(int i = 1; i <= n ;i++){
scanf("%d", &a[i]);
a[i] = table[a[i]] ? table[a[i]] : table[a[i]] = ++num ;//离散化
//如果table[a[i]] 有值,那么a[i] = table[a[i]],相当于编号,如果没有,那么向后推
G[a[i]].push_back(i);//记录值为a[i]的各个数的位置
}
unit = (int)sqrt(1.0*n);
scanf("%d", &m);
int l, r;
for(int i = 1; i <= m; i++){
scanf("%d%d", &l, &r);
r = l + r - 1;
int pos = lower_bound(G[a[r]].begin(), G[a[r]].end(), l) - G[a[r]].begin();//二分得到r再l的右边最先出现过的位置
r = G[a[r]][pos] ;
b[i].l = l; b[i].r = r; b[i].id = i;
}
modui();
}
return 0;
}