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

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

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

那怎么做呢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;
} 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值