HH的项链 (求区间内有多少个不同的数字)
Posted 昵称很长很长真是太好了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HH的项链 (求区间内有多少个不同的数字)相关的知识,希望对你有一定的参考价值。
这种题之前用莫队做过,这几天看到了一个树状数组的解法,十分巧妙,不卡常,应用广,估计会广泛与其他类型题目结合。
题解:
由于本题可以离线查询,那么我们将其查询按照右端点进行排序。
然后从小到大开始遍历这个序列,如果这个数没出现过,那么我们便在当前位置+1,若之前出现过,那么我们在之前出现的位置上-1,然后当前位置上+1.(因为统计的是不同数字的个数,所以我们统计离r结点最近的即可)。
如果遇到r等于i时,我们就统计答案,答案为区间l-r的和。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int pos[maxn];
int a[maxn];
int n;
struct stu{
int l,r,id;
bool operator<(const stu & a)const{
return r<a.r;
}
}pp[maxn];
int c[maxn];
int lowbit(int x){
return x&(-x);
}
void update(int i,int k){
while(i<=n){
c[i]+=k;
i+=lowbit(i);
}
}
int getsum(int i){
int res=0;
while(i>0){
res+=c[i];
i-=lowbit(i);
}
return res;
}
int ans[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d",&pp[i].l);
scanf("%d",&pp[i].r);
pp[i].id=i;
}
sort(pp+1,pp+1+q);
int nowpos=1;
for(int i=1;i<=n;i++){
if(pos[a[i]]==0){
update(i,1);
}
else{
update(pos[a[i]],-1);
update(i,1);
}
pos[a[i]]=i;
while(pp[nowpos].r==i){
ans[pp[nowpos].id]=getsum(pp[nowpos].r)-getsum(pp[nowpos].l-1);
nowpos++;
}
}
for(int i=1;i<=q;i++){
printf("%d\\n",ans[i]);
}
}
以上是关于HH的项链 (求区间内有多少个不同的数字)的主要内容,如果未能解决你的问题,请参考以下文章