求区间种类数——树状数组

一提到求区间种类数….脑子里满是莫队啊啊啊怕不是没救了……..

题意很简单,就是求区间内有多少个不同的数

那怎么做呢qaq 树状数组诶!

把所有询问按右端点排序,然后每次加到这个点

树状数组按位置建哦
那么树状数组上每个点就记录第一个点到此点有多少个数,因为此时查询的右端点是一点定的,所有每个数都记他最后一次出现的位置,这样也可以保证不会重。
而且查询的时候,因为左端点不一定,所以答案是query(tmp)-query(x-1)。记录每个数最后一次出现的位置,会保证不会减重了,而不会减多了

是不是很妙啊!

来一发例题 bzoj1878

#include 
#include 
#include 
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.yvoid 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(tmpif(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;
} 

你可能感兴趣的:(树状数组)