题解:解法一:莫队
解法二:按区间左端点排序,让区间内最左边的贝壳对答案产生贡献,树状数组维护,转移对答案产生贡献的贝壳位置
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1000009; int n,m; int a[maxn]; int nex[maxn]; int ans[maxn]; int tong[maxn]; inline int lowbit(int x){ return x&(-x); } int c[maxn]; int add(int x,int val){ while(x<=1000001){ c[x]+=val; x+=lowbit(x); } } int query(int x){ int ret=0; while(x){ ret+=c[x]; x-=lowbit(x); } return ret; } struct Section{ int l,r,id; }sec[maxn]; int cmp(const Section &t1,const Section &t2){ if(t1.l==t2.l)return t1.r<t2.r; else return t1.l<t2.l; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); if(a[i]==0)a[i]=1000001; } for(int i=n;i>=1;--i){ if(!tong[a[i]]){ nex[i]=n+1; }else{ nex[i]=tong[a[i]]; } tong[a[i]]=i; } scanf("%d",&m); for(int i=1;i<=m;++i){ scanf("%d%d",&sec[i].l,&sec[i].r); sec[i].id=i; } sort(sec+1,sec+1+m,cmp); memset(tong,0,sizeof(tong)); for(int i=1;i<=n;++i){ if(!tong[a[i]])add(i,1); tong[a[i]]=1; } int head=1; for(int i=1;i<=m;++i){ while(head<sec[i].l){ add(head,-1); add(nex[head],1); ++head; } ans[sec[i].id]=query(sec[i].r)-query(sec[i].l-1); } for(int i=1;i<=m;++i)printf("%d\n",ans[i]); return 0; }