P1903 数颜色
P1903 数颜色
Description
对于每个位置,有颜色。有两个操作,修改当前位置颜色、查询 \([L,R]\) 区间内颜色种类数。
Solution
我们考虑带修莫队。
由于询问都是按照莫队排序,所以未必按照时间轴排序,我们考虑记下当前询问的最新修改时间戳,而后我们对于这样一个时间戳进行还原。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+8;
int n,m,len;
int col[N];
int belongs[N];
char op;
int cntq,cntp;
int res[N];
int ans;
int cnt[N];
int l,r,t;
struct node1{
int l,r,t,id;
friend bool operator < (node1 a,node1 b){
return belongs[a.l]==belongs[b.l]?belongs[a.r]==belongs[b.r]?a.t<b.t:belongs[a.r]<belongs[b.r]:belongs[a.l]<belongs[b.l];
}
}Q[N];
struct node2{
int pos,col;
}P[N];
void add(int x){if(!cnt[x])ans++;cnt[x]++;}
void del(int x){cnt[x]--;if(!cnt[x])ans--;}
void upd(node1 q,node2 &p){
if(q.l<=p.pos&&p.pos<=q.r) del(col[p.pos]),add(p.col);
swap(col[p.pos],p.col);
}
void solve(node1 q){
while(l>q.l) add(col[--l]);
while(r<q.r) add(col[++r]);
while(l<q.l) del(col[l++]);
while(r>q.r) del(col[r--]);
while(t<q.t) upd(q,P[++t]);
while(t>q.t) upd(q,P[t--]);
res[q.id]=ans;
}
int main(){
scanf("%d%d",&n,&m);
len=pow(n,0.666);
for(int i=1;i<=n;i++) scanf("%d",&col[i]),belongs[i]=(i-1)/len+1;
for(int i=1;i<=m;i++){
scanf("%s",&op);
if(op=='Q') cntq++,scanf("%d%d",&Q[cntq].l,&Q[cntq].r),Q[cntq].t=cntp,Q[cntq].id=cntq;
else cntp++,scanf("%d%d",&P[cntp].pos,&P[cntp].col);
}
sort(Q+1,Q+1+cntq);
l=1,r=0,t=0;
for(int i=1;i<=cntq;i++) solve(Q[i]);
for(int i=1;i<=cntq;i++) printf("%d\n",res[i]);
return 0;
}