板子:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
int n,m;
int a[maxn];
int where[maxn];
struct Query{
int x,y,pre,id;
}Q[maxn];
int Qnum = 0;
struct Change{
int pos;
int val;
}C[maxn];
int Cnum = 0;
int color[maxn];
int ans = 0;
int base;
int out[maxn];
int cmp(Query a,Query b){
if(a.x != b.x) return where[a.x] < where[b.x];
if(a.y != b.y) return where[a.y] < where[b.y];
return a.pre < b.pre;
}
inline void add(int x){
if(++color[x] == 1) ans++;
}
inline void del(int x){
if(--color[x] == 0) ans--;
}
void work(int now,int i){
if(C[now].pos >= Q[i].x&&C[now].pos <= Q[i].y){
if(--color[a[C[now].pos]] == 0) ans--;
if(++color[C[now].val] == 1) ans++;
}
swap(C[now].val,a[C[now].pos]);
}
void MoQuery(){
int l = 1; int r = 0;
int now = 0;
for(int i = 1;i <= m;i++){
while(l < Q[i].x) del(a[l++]);
while(r > Q[i].y) del(a[r--]);
while(l > Q[i].x) add(a[--l]);
while(r < Q[i].y) add(a[++r]);
while(now < Q[i].pre) work(++now,i);
while(now > Q[i].pre) work(now--,i);
out[Q[i].id] = ans;
}
for(int i = 1;i <= Qnum;i++){
printf("%d\n",out[i]);
}
}
int main(){
scanf("%d%d",&n,&m);
base = sqrt(n);
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
where[i] = (i - 1) / base + 1;
}
while(m--){
char opt[5];
scanf("%s",opt);
if(opt[0] == 'Q'){
++Qnum;
scanf("%d%d",&Q[Qnum].x,&Q[Qnum].y);
Q[Qnum].pre = Cnum;
Q[Qnum].id = Qnum;
}
else if(opt[0] == 'R'){
++Cnum;
scanf("%d%d",&C[Cnum].pos,&C[Cnum].val);
}
}
sort(Q + 1,Q + 1 + Qnum,cmp);
MoQuery();
return 0;
}