解题思路
将询问按右端点排序。对于区间[1~R],保证在每种颜色最后出现的位置为1,用树状数组和双向链表维护,就可以快速求解了。
代码:
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct ldx {
int x,y,num;
bool operator < (const ldx &p) const{
return y>p.y;
}
}s[200005];
int a[50005],b[50005],ans[200005];
int p[50005],sh[50005],f[50005];
int n,m;
void add(int x,int num){
if(num==0) return ;
while(num<=n){
p[num]+=x;
num+=num&(-num);
}
}
int ch(int num){
int j=0;
while(num>0){
j+=p[num];
num-=num&(-num);
}
return j;
}
int main(){
int r1,r2;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
int top=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+top+1,a[i])-b;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&s[i].x,&s[i].y);
s[i].num=i;
}
sort(s+1,s+m+1);
for(int i=1;i<=n;i++){
sh[i]=f[a[i]];
f[a[i]]=i;
}
int fm=m;
for(int i=1;i<=n;i++){
add(1,i);add(-1,sh[i]);
while(s[m].y==i){
ans[s[m].num]=ch(s[m].y)-ch(s[m].x-1);
m--;
}
}
for(int i=1;i<=fm;i++) printf("%d\n",ans[i]);
return 0;
}