一提到求区间种类数….脑子里满是莫队啊啊啊怕不是没救了……..
题意很简单,就是求区间内有多少个不同的数
那怎么做呢qaq 树状数组诶!
把所有询问按右端点排序,然后每次加到这个点
树状数组按位置建哦
那么树状数组上每个点就记录第一个点到此点有多少个数,因为此时查询的右端点是一点定的,所有每个数都记他最后一次出现的位置,这样也可以保证不会重。
而且查询的时候,因为左端点不一定,所以答案是query(tmp)-query(x-1)。记录每个数最后一次出现的位置,会保证不会减重了,而不会减多了
是不是很妙啊!
来一发例题 bzoj1878
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 500050
#define M 200020
int mx=0,n,m,b[N],ans[N],tree[N<<1],last[N],h[N<<1];
struct node{int x,y,num;}a[M];
bool cmp(node x,node y){return x.y<y.y || (x.y==y.y && x.x<y.x);}
void insert(int x,int y){for(;x<=n;x+=x&-x) tree[x]+=y;}
int query(int x){
int y=0;for(;x;x-=x&-x) y+=tree[x];
return y;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&b[i]),last[i]=h[b[i]],h[b[i]]=i,mx=max(mx,b[i]);
scanf("%d",&m);int q=sqrt(n);
for(int i=1;i<=m;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].num=i;
sort(a+1,a+m+1,cmp);int tmp=0;
for(int i=1;i<=m;i++){
while(tmp<a[i].y){
tmp++;if(last[tmp]) insert(last[tmp],-1);
insert(tmp,1);
}ans[a[i].num]=query(tmp)-query(a[i].x-1);
}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}