普通莫队一般是不带修改的,但是有一些题目是需要修改的…
比如BZOJ2120。
这题如果没有修改,那大概就是个莫队裸题,但是它现在带修改了,就需要一些操作了。
我们把对于询问的结构体记录一个上一次的修改,例如第5次询问是在第3次修改之后进行的。
那么如果我们需要询问第5次询问,现在修改还在第1次,我们就把修改改成2,3次之后,再进行询问就可以了。思想上还是莫队。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6+7;
int n,m,qnum,cnum,block,Ans = 0;
int a[maxn],b[maxn],cnt[maxn],ans[maxn];
struct node
{
int x,y,pre,id;
bool operator<(const node &rhs)const
{
if(b[x]!=b[rhs.x]) return b[x]<b[rhs.x];
if(b[y]!=b[rhs.y]) return b[y]<b[rhs.y];
return pre<rhs.pre;
}
}Q[maxn];
struct change
{
int pos,x;
}C[maxn];
void add(int x)
{
if(++cnt[x]==1) Ans++;
}
void del(int x)
{
if(--cnt[x]==0) Ans--;
}
void gao(int now,int o)
{
if(Q[o].x<=C[now].pos && Q[o].y>=C[now].pos)
{
if(--cnt[a[C[now].pos]]==0) Ans--;
if(++cnt[C[now].x]==1) Ans++;
}
swap(a[C[now].pos],C[now].x);
}
void solve()
{
int l = 1,r = 0,now = 0;
for(int i=1;i<=qnum;i++)
{
while(l<Q[i].x) del(a[l++]);
while(l>Q[i].x) add(a[--l]);
while(r<Q[i].y) add(a[++r]);
while(r>Q[i].y) del(a[r--]);
while(now<Q[i].pre) gao(++now,i);
while(now>Q[i].pre) gao(now--,i);
ans[Q[i].id] = Ans;
}
for(int i=1;i<=qnum;i++) printf("%d\n",ans[i]);
}
int main()
{
scanf("%d%d",&n,&m);
block = sqrt(n*2.0/3.0);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
b[i] = i/block+1;
}
for(int i=0;i<m;i++)
{
char op[5];
scanf("%s",op);
if(op[0]=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
Q[++qnum].x = l;
Q[qnum].y = r;
Q[qnum].pre = cnum;
Q[qnum].id = qnum;
}
else if(op[0]=='R')
{
int x,y;
scanf("%d%d",&x,&y);
C[++cnum].pos = x;
C[cnum].x = y;
}
}
sort(Q+1,Q+1+qnum);
solve();
return 0;
}