题意:
给定n朵花,第i朵花对应颜色a[i],有m次询问,每次询问[l,r]之间可以采到的花的颜色数。(采花时,如果采花区间内某种颜色的花只有1多,这朵花是不采的)
数据范围:
思路:
项链问题的变种 HH的项链--思维(查询区间种类数)_枫茗、的博客-CSDN博客
我们除了pre数组外还需要一个ppre数组,这里要记录前两个位置,遍历到当前位置i时,ppre[a[i]]位置的贡献清零,pre[a[i]]的位置贡献加1,将ppre[a[i]]=pre[a[i]],pre[a[i]]=i。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int n,c,m;
int tr[N],a[N],ans[N];
int ppre[N],pre[N];
typedef struct Segment{
int l,r,id;
}Segment;
Segment seg[N];
bool cmp(Segment a,Segment b){
return a.r<b.r;
}
int lowbit(int x){
return x&(-x);
}
void modify(int x,int k){
while(x<=n){
tr[x]+=k;
x+=lowbit(x);
}
}
int query(int x){
int res=0;
while(x){
res+=tr[x];
x-=lowbit(x);
}
return res;
}
int main(){
scanf("%d%d%d",&n,&c,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++){
scanf("%d%d",&seg[i].l,&seg[i].r);
seg[i].id=i;
}
sort(seg+1,seg+m+1,cmp);
int j=1;
//ppre为前前,pre为前,i为当前
for(int i=1;i<=n;i++){
if(!pre[a[i]]){
pre[a[i]]=i;
}
else if(!ppre[a[i]]){
ppre[a[i]]=pre[a[i]];
modify(ppre[a[i]],1);
pre[a[i]]=i;
}
else{
modify(ppre[a[i]],-1);
modify(pre[a[i]],1);
ppre[a[i]]=pre[a[i]];
pre[a[i]]=i;
}
while(j<=m&&seg[j].r==i){
ans[seg[j].id]=query(seg[j].r)-query(seg[j].l-1);
j++;
}
}
for(int i=1;i<=m;i++){
printf("%d\n",ans[i]);
}
}