莫队
#include<bits/stdc++.h>
using namespace std;
const int N=50010,M=200100,K=1e6+2022;
int read(){
int x=0,f=1;char c=getchar();
while(c>'9' || c<'0'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int L,R,n,m,a[N],now[K],cnt,ans[M],tmp;
struct node{
int l,r,x;
}e[M];
bool cmp(node t1,node t2){
if(t1.l/tmp==t2.l/tmp)return t1.r<t2.r;
return t1.l/tmp<t2.l/tmp;
}
void add(int t){
if(t==0)return;
t=a[t];
now[t]++;
if(now[t]==1)cnt++;
return;
}
void del(int t){
if(t==0)return;
t=a[t];
now[t]--;
if(now[t]==0)cnt--;
return;
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
m=read();
for(int i=1;i<=m;i++){
e[i].l=read(),e[i].r=read();
e[i].x=i;
}
tmp=sqrt(n);
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
while(R<e[i].r)add(++R);
while(L>e[i].l)add(--L);
while(R>e[i].r)del(R--);
while(L<e[i].l)del(L++);
ans[e[i].x]=cnt;
}
for(int i=1;i<=m;i++){
printf("%d\n",ans[i]);
}
return 0;
}
带修莫队
#include<bits/stdc++.h>
using namespace std;
const int N=133333+2022,M=1e6+2022;
int read(){
int x=0,f=1;char c=getchar();
while(c>'9' || c<'0'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int ans[N],n,m,a[N],tmp,tot,cnt,now[M],L,R,sum,T;
struct node{
int l,r,t,num;
}e[N];
struct SYS{
int va,wz;
}x[N];
bool cmp(node t1,node t2){
if(t1.l/tmp==t2.l/tmp && t1.r/tmp==t2.r/tmp)return t1.t<t2.t;
if(t1.l/tmp==t2.l/tmp)return t1.r/tmp<t2.r/tmp;
return t1.l/tmp<t2.l/tmp;
}
void add(int u){
if(u==0)return;
u=a[u];
now[u]++;
if(now[u]==1)sum++;
return;
}
void del(int u){
if(u==0)return;
u=a[u];
now[u]--;
if(now[u]==0)sum--;
return;
}
void time(int u){
if(L<=x[u].wz && x[u].wz<=R){
now[a[x[u].wz]]--;
if(now[a[x[u].wz]]==0)sum--;
now[x[u].va]++;
if(now[x[u].va]==1)sum++;
}
swap(a[x[u].wz],x[u].va);
return;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
tmp=pow(n,0.666);
for(int i=1;i<=m;i++){
char opt;
cin>>opt;
int t1=read(),t2=read();
if(opt=='Q'){
e[++tot].l=t1,e[tot].r=t2;
e[tot].num=tot;
e[tot].t=cnt;
}
else{
x[++cnt].wz=t1,x[cnt].va=t2;
}
}
sort(e+1,e+tot+1,cmp);
for(int i=1;i<=tot;i++){
while(L<e[i].l)del(L++);
while(R>e[i].r)del(R--);
while(L>e[i].l)add(--L);
while(R<e[i].r)add(++R);
while(T<e[i].t)time(++T);
while(T>e[i].t)time(T--);
ans[e[i].num]=sum;
}
for(int i=1;i<=tot;i++)
printf("%d\n",ans[i]);
return 0;
}
CDQ分治