题意
带修莫队与普通莫队的区别在于加入了一个时间轴,具体可以看这篇博客。
另外,这是卡常神题。
code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
#pragma GCC target("f16c")
#pragma GCC target("fma","avx2")
#pragma GCC target("xop","fma4")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#include<bits/stdc++.h>
using namespace std;
#define re register
const int maxn=150010;
const int maxm=150010;
int n,m,cnt1,cnt2,nowtim,nowl=1,nowr,nowans;
int a[maxn],b[maxn],pos[maxn],cnt[1000010],ans[maxm];
struct Query{int tim,l,r,id;}qr[maxm];
struct Change{int pos,last,now;}ctim[maxm];
inline bool cmp(Query x,Query y){return pos[x.l]==pos[y.l]?(pos[x.r]==pos[y.r]?x.tim<y.tim:x.r<y.r):x.l<y.l;}
inline int read()
{
char c=getchar();re int res=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
return res*f;
}
inline void add(int x)
{
cnt[x]++;
if(cnt[x]==1)nowans++;
}
inline void del(int x)
{
cnt[x]--;
if(!cnt[x])nowans--;
}
inline void move(int pos,int k)
{
if(pos>=nowl&&pos<=nowr)del(a[pos]),a[pos]=k,add(a[pos]);
a[pos]=k;
}
int main()
{
n=read(),m=read();
for(re int i=1;i<=n;i++)a[i]=b[i]=read();
for(re int i=1;i<=m;i++)
{
char op[10];scanf("%s",op);
re int x=read(),y=read();
if(op[0]=='Q')qr[++cnt1]=(Query){cnt2,x,y,cnt1};
else ctim[++cnt2]=(Change){x,b[x],y},b[x]=y;
}
re int t=pow(n,1.0*5/7);
for(re int i=1;i<=n;i++)pos[i]=(i-1)/t+1;
sort(qr+1,qr+cnt1+1,cmp);
for(re int i=1;i<=cnt1;i++)
{
while(nowtim<qr[i].tim)move(ctim[nowtim+1].pos,ctim[nowtim+1].now),nowtim++;
while(nowtim>qr[i].tim)move(ctim[nowtim].pos,ctim[nowtim].last),nowtim--;
while(nowl>qr[i].l)add(a[--nowl]);
while(nowl<qr[i].l)del(a[nowl++]);
while(nowr>qr[i].r)del(a[nowr--]);
while(nowr<qr[i].r)add(a[++nowr]);
ans[qr[i].id]=nowans;
}
for(re int i=1;i<=cnt1;i++)printf("%d
",ans[i]);
return 0;
}