1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <algorithm> 5 #define reg register 6 using namespace std; 7 const int MN=50005,NM=200005; 8 int h[MN],n,q,a[MN],ans[NM]; 9 struct data{ 10 int l,r,id; 11 bool operator<(const data&b)const{ 12 if (h[l]==h[b.l]) return r<b.r;//如果左端点在同一块,按右端点排序 13 return l<b.l;//否则按左端点排序 14 } 15 }que[NM]; 16 inline int ri(){ 17 char c=getchar();int x=0,w=1; 18 while(!isdigit(c)){if(c=='-')w=-1;c=getchar();} 19 while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();} 20 return x*w; 21 } 22 inline void blocker(){ 23 int k=sqrt(n); 24 for(reg int i=1;i<=n;i++)h[i]=(i-1)/k+1;//分出根号n个块 25 } 26 int L,R,now,hsh[1000005]; 27 inline void move(int x,int d){ 28 if (d==1){ 29 if(hsh[a[x]]==0)now++; hsh[a[x]]++; 30 } 31 else{ 32 hsh[a[x]]--; if(hsh[a[x]]==0)now--; 33 } 34 } 35 int main(){ 36 n=ri(); 37 for(reg int i=1;i<=n;i++)a[i]=ri(); 38 blocker(),q=ri(); 39 for(reg int i=1;i<=q;i++) que[i].l=ri(),que[i].r=ri(),que[i].id=i; 40 sort(que+1,que+1+q); 41 for(reg int i=1;i<=q;i++){ 42 while (L<que[i].l) move(L++,-1);//缩小 43 while (L>que[i].l) move(--L,1);//扩大 44 while (R<que[i].r) move(++R,1);//扩大 45 while (R>que[i].r) move(R--,-1);//缩小 46 ans[que[i].id]=now; 47 } 48 for(reg int i=1;i<=q;i++) printf("%d\n",ans[i]); 49 return 0; 50 }