带修改莫队经典题目
关于莫队的一篇很好的blog
题目描述
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
为了满足墨墨的要求,你知道你需要干什么了吗?
输入格式
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。
第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。
第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
输出格式
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
带修改莫队无非是在原先莫队算法的基础增加了修改操作,是不同时间查询不同,我们在原先莫队算法的基础上加上了时间戳,及不仅通过l和r维护区间,也通过时间戳来判断合适的时间。
一开始蜜汁错误
好在最后A掉了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=2e6+100;
ll a[maxn];
ll be[maxn];
ll ans[maxn];
ll cnt[maxn];
struct Q{
ll l,r,t,id;
friend bool operator <(Q a,Q b){
return (be[a.l]^be[b.l])?be[a.l]<be[b.l]:((be[a.r]^be[b.r])?be[a.r]<be[b.r]:a.t<b.t);
}
}q[maxn];
struct M{
ll pos,color;
}mo[maxn];
inline ll read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
return x*f;
}
int main(){
ll n=read(),m=read();
ll sz=pow(n,2.0/3);
for(ll i=1;i<=n;i++){
a[i]=read();
be[i]=i/sz;
}
ll cntq=0,cntm=0;
for(ll i=1;i<=m;i++){
char op[5];
ll l,r,pos,color;
scanf("%s",op);
if(op[0]=='Q'){
l=read();
r=read();
q[++cntq].l=l;
q[cntq].r=r;
q[cntq].t=cntm;
q[cntq].id=cntq;
}
else{
pos=read();
color=read();
mo[++cntm].pos=pos;
mo[cntm].color=color;
}
}
sort(q+1,q+1+cntq);
ll l=1,r=0,t=0,res=0;
for(ll i=1;i<=cntq;i++){
ll ql=q[i].l;
ll qr=q[i].r;
ll qt=q[i].t;
while(l<ql){
cnt[a[l]]--;
if(cnt[a[l]]==0)
res--;
l++;
}
while(l>ql){
l--;
if(cnt[a[l]]==0)
res++;
cnt[a[l]]++;
}
while(r>qr){
cnt[a[r]]--;
if(cnt[a[r]]==0)
res--;
r--;
}
while(r<qr){
r++;
if(cnt[a[r]]==0)
res++;
cnt[a[r]]++;
}
while(t<qt){
t++;
if(mo[t].pos>=l&&mo[t].pos<=r){
cnt[a[mo[t].pos]]--;
if(cnt[a[mo[t].pos]]==0)
res--;
if(cnt[mo[t].color]==0)
res++;
cnt[mo[t].color]++;
}
swap(mo[t].color,a[mo[t].pos]);
}
while(t>qt){
if(mo[t].pos>=l&&mo[t].pos<=r){
cnt[a[mo[t].pos]]--;
if(cnt[a[mo[t].pos]]==0)
res--;
if(cnt[mo[t].color]==0)
res++;
cnt[mo[t].color]++;
}
swap(mo[t].color,a[mo[t].pos]);
t--;
}
ans[q[i].id]=res;
}
for(ll i=1;i<=cntq;i++){
printf("%lld\n",ans[i]);
}
}