离线+树状数组 给出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
- Line 1: n (1 ≤ n ≤ 30000).
- Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
- Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
- In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).
Output
- For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.
Example
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;
}