[国家集训队]数颜色 / 维护队列
考虑这是一个带修改的莫队。
我们多加一维时间轴。
发现这个修改是很平凡的。
所以我们的操作也就从二维转到了三维。
记录每个查询要修改的操作次数,多了就还原,少了就去掉。
[国家集训队]数颜色 / 维护队列
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 1400000
int n,m,a[N];
char k;
ll cntq,cntr;
struct P{
int l,r,t,id;
}qq[N],qr[N];
ll sz;
bool cmp(P a,P b){
return (a.l / sz == b.l / sz) ? (a.r / sz == b.r / sz) ? a.t < b.t : a.r < b.r : a.l < b.l;
}
ll c[N],ans[N],qans;
inline void add(ll x){qans += !c[x] ++ ;}
inline void del(ll x){qans -= ! -- c[x];}
inline void modity(ll i,ll ct){
if(qr[ct].l >= qq[i].l && qr[ct].l <= qq[i].r){
del(a[qr[ct].l]);
add(qr[ct].r);
}
std::swap(a[qr[ct].l],qr[ct].r);
}
int main(){
scanf("%d%d",&n,&m);
sz = pow(n,0.66666);
for(int i = 1;i <= n;++i)
scanf("%d",&a[i]);
for(int i = 1;i <= m;++i){
while(k != 'R' && k != 'Q')
k = getchar();
ll l,r;
scanf("%d%d",&l,&r);
if(k == 'Q'){
qq[++cntq].l = l;
qq[cntq].r = r;
qq[cntq].id = cntq;
qq[cntq].t = cntr;
}
else
qr[++cntr].l = l,qr[cntr].r = r;
k = 'Z';
}
std::sort(qq + 1,qq + cntq + 1,cmp);
ll l = 0,r = 0,t = 0;
for(int i = 1;i <= cntq;++i){
while(l < qq[i].l)del(a[l ++ ]);
while(l > qq[i].l)add(a[-- l]);
while(r > qq[i].r)del(a[r --]);
while(r < qq[i].r)add(a[++ r]);
while(t < qq[i].t)modity(i,++t);
while(t > qq[i].t)modity(i,t--);
ans[qq[i].id] = qans;
}
for(int i = 1;i <= cntq;++i)
std::cout<<ans[i]<<std::endl;
}