板子题
带修莫队的的和普通莫队的区别就在于增加了修改操作
在一操作,求完之后在看修改的,把修改的部分加上去,加到该次操作之前
另外这里的块大小应该设为 n 2 3 n^{\frac{2}{3}} n32才能过,一般的根号过不了
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re register int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=1e9+7;
const int M=1e9;
const int N=2e6+5;//?????????? 4e8
struct nc
{
int l,r,pre,id;
}q[N];
struct node
{
int pos,val;
}c[N];
int qnum,cnum,n,m,a[N],v[N];
int siz;
int ans,qes[N];
int cmp(nc i,nc j)
{
if(i.l/siz!=j.l/siz) return i.l/siz<j.l/siz;
if(i.r/siz!=j.r/siz) return i.r/siz<j.r/siz;
return i.pre<j.pre;
}
void add(int x)
{
if(++v[a[x]]==1) ans++;
}
void del(int x)
{
if(--v[a[x]]==0) ans--;
}
void work(int now,int i)
{
if(c[now].pos>=q[i].l&&c[now].pos<=q[i].r)
{
if(--v[a[c[now].pos]]==0) ans--;
if(++v[c[now].val]==1) ans++;
}
swap(c[now].val,a[c[now].pos]);
}
void solve()
{
int l=1,r=0,now=0;
cin>>n>>m;
siz=pow(n,2.0/3.0);
for(re i=1;i<=n;i++) scanf("%d",&a[i]);
for(re i=1;i<=m;i++)
{
char op[10];
int l,r;
scanf("%s%d%d",op,&l,&r);
if(op[0]=='Q') q[++qnum]=(nc){l,r,cnum,qnum};
else c[++cnum]=(node){l,r};
}
sort(q+1,q+qnum+1,cmp);
for(re i=1;i<=qnum;i++)
{
while(l<q[i].l) del(l++);
while(l>q[i].l) add(--l);
while(r<q[i].r) add(++r);
while(r>q[i].r) del(r--);
while(now<q[i].pre) work(++now,i);
while(now>q[i].pre) work(now--,i);
qes[q[i].id]=ans;
}
for(re i=1;i<=qnum;i++) printf("%d\n",qes[i]);
}
signed main()
{
// freopen("P1505_1.txt", "r", stdin);
// freopen("Aout.txt", "w", stdout);
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
// printf("Case #%lld: ",index);
solve();
// puts("");
}
return 0;
}
/*
*/