离线+树状数组 给出N (1 <= N <= 30000) 个正整数 (<= 10 ^ 6) 和Q (1 <= Q <= 200000) 个询问,每次查询区间 [i, j] 内有多少个不同的数。
Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, ..., aj.
Input 5 1 1 2 1 3 3 1 5 2 4 3 5 Output 3 2 3
#include<stdio.h> #include<string.h> #include<algorithm> #define lowbit(x) ((x)&(-x)) using namespace std; typedef struct query { int x,y; int id; inline bool operator < (query t) const { return y < t.y; } }query; query Q[200001]; int a[30001],pre[1000001]={0}; int ans[200001]; int cc[30010]={0}; void update(int a,int d) { while(a<=30000) { cc[a]+=d; a+=lowbit(a); } } int getsum(int a) { int sum=0; while(a>0) { sum+=cc[a]; a-=lowbit(a); } return sum; } int main() { int n,i,j,q,c,d,cur; scanf("%d",&n); memset(pre,0,sizeof(pre)); memset(cc,0,sizeof(cc)); for(i=1;i<=n;i++) scanf("%d",a+i); scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%d%d",&c,&d); Q[i].x=c; Q[i].y=d; Q[i].id=i; } sort(Q+1,Q+q+1);//按照询问的右端点排序 for(i=1,cur=1;i<=q;i++) // 在每个询问的右端点前面插入比它序号小的数 { for(;cur<=Q[i].y;cur++) { update(pre[a[cur]]+1,1); //在[pre[a[cur]]+1,cur]这一段区间加上1 update(cur+1,-1); pre[a[cur]]=cur;//记录上一次出现a[cur]值的下标号 } ans[Q[i].id]=getsum(Q[i].x); } for(j=1;j<=q;j++) printf("%d\n",ans[j]); return 0; }