题意:
对给定的序列,回答m个询问,Q:询问l到r中不同的颜色数量,R:将下标为x的颜色改为y
题解:
带修莫队,相对普通的莫队,加多了一个关键字排序
#include<bits/stdc++.h>
#define num ch-'0'
#define pn putchar('\n')
using namespace std;
template<typename T>
void read(T &res) {
bool flag=false;char ch;
while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getchar());res=res*10+num);
flag&&(res=-res);
}
template<typename T>
void write(T x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int maxn=50010;
const int M=50010;
int n,m;
int qu_num,op_num;
int lst[maxn],col[maxn],blo[maxn],cnt[1000010],res[M];
struct query{
int l,r,t,pos;
bool operator <(const query &a) const {
return blo[a.l]==blo[l]?(blo[a.r]==blo[r]?t<a.t:blo[r]<blo[a.r]):blo[l]<blo[a.l];
}
}qu[M];
struct oper {
int x,lst,now;
}op[M];
int main()
{
read(n),read(m);
int q=pow(n,0.666666);
for(int i=1;i<=n;i++)
read(col[i]),blo[i]=(i-1)/q+1,lst[i]=col[i];
int x,y;
for(int i=1;i<=m;i++) {
char ch[5];
scanf("%s",ch);
scanf("%d%d",&x,&y);
if(ch[0]=='Q')
qu[++qu_num].l=x,qu[qu_num].r=y,qu[qu[qu_num].pos=qu_num].t=op_num;
else
op[++op_num].x=x,op[op_num].lst=lst[x],op[op_num].now=y,lst[x]=y;
}
sort(qu+1,qu+1+qu_num);
int l=0,r=0,t=0,ans=0;
for(int i=1;i<=qu_num;i++) {
while(t<qu[i].t) {
t++; ///最初的t=0,先增
if(l<=op[t].x&&op[t].x<=r) {
if(!--cnt[col[op[t].x]]) ans--;
if(!cnt[op[t].now]++) ans++;
}
col[op[t].x]=op[t].now;
}
while(t>qu[i].t) {
if(l<=op[t].x&&op[t].x<=r) {
if(!--cnt[col[op[t].x]]) ans--;
if(!cnt[op[t].lst]++) ans++;
}
col[op[t].x]=op[t].lst;
t--;
}
while(r<qu[i].r) if(!cnt[col[++r]]++) ans++;
while(l>qu[i].l) if(!cnt[col[--l]]++) ans++;
while(r>qu[i].r) if(!--cnt[col[r--]]) ans--;
while(l<qu[i].l) if(!--cnt[col[l++]]) ans--;
res[qu[i].pos]=ans;
}
for(int i=1;i<=qu_num;i++)
write(res[i]),pn;
return 0;
}