http://www.cnblogs.com/proverbs/archive/2012/10/29/2745281.html
(↑)这样处理之后,每次询问时,对于每种颜色,从1到其倒数第二次出现的位置都会被覆盖1次,因此询问左端点的值即可。
#include<cstdio> #include<algorithm> using namespace std; #define N 1000001 int n,K,m,a[N],pre[N],anss[N],now[N]; struct ASK{int l,r,id;}Q[N]; bool operator < (ASK a,ASK b){return a.r<b.r;} int d[N]; void Update(int p,int v){for(;p<=n;p+=(p&(-p))) d[p]+=v;} void UpdateRange(int L,int R){Update(L,1); if(R<n) Update(R+1,-1);} int Query(int p){int res=0; for(;p;p-=(p&(-p))) res+=d[p]; return res;} int main() { scanf("%d%d%d",&n,&K,&m); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); pre[i]=now[a[i]]; now[a[i]]=i; } for(int i=1;i<=m;++i) { scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id=i; } sort(Q+1,Q+m+1); for(int i=1;i<=m;++i) { for(int j=Q[i-1].r+1;j<=Q[i].r;++j) if(pre[j]) UpdateRange(pre[pre[j]]+1,pre[j]); anss[Q[i].id]=Query(Q[i].l); } for(int i=1;i<=m;++i) printf("%d ",anss[i]); return 0; }