参考例题:luoguP1903[国家集训队]数颜色 / 维护队列
#include<bits/stdc++.h>
#define N 150005
#define in read()
#define re register//一堆优化
using namespace std;
int n,m,k,a[N],num[1000005],ans[N],zhi,from[N],l,r,now;
struct zb{
int l,r,poi,ti;}q[N];
int Cnum=0,Qnum=0;
struct Change{
int pos,val;
}c[N];
inline int in{
int i=0;char ch;
while(!isdigit(ch)){ch=getchar();}
while(isdigit(ch)){i=(i<<3)+(i<<1)+(ch-'0');ch=getchar();}
return i;
}
inline bool cmp(zb a,zb b)//顺序:左右时.
{
if(from[a.l]!=from[b.l])return a.l<b.l;
if(from[a.r]!=from[b.r])return a.r<b.r;
return a.ti<b.ti;
}
inline void work(int tim)//带修莫队核心
{
if(c[tim].pos>=l&&c[tim].pos<=r)
{
if(!--num[a[c[tim].pos]])--zhi;
if(++num[c[tim].val]==1)++zhi;
}
swap(a[c[tim].pos],c[tim].val);
return;
}
int main()
{
n=in,m=in;
int block=pow(n,2.0/3.0);//这样取值可以得到最优复杂度
char opt;
for(re int i=1;i<=n;i++)
{
a[i]=in;
from[i]=(i-1)/block+1;
}
while(m--)//用Qnum和Cnum分别记录询问和修改的次数
{
cin>>opt;
if(opt=='Q')
{
q[++Qnum].l=in;
q[Qnum].r=in;
q[Qnum].ti=Cnum;
q[Qnum].poi=Qnum;
}
else if(opt=='R')
{
c[++Cnum].pos=in;
c[Cnum].val=in;
}
}
sort(q+1,q+Qnum+1,cmp);
l=1,r=0,now=0;
for(re int i=1;i<=Qnum;i++)
{
while(l<q[i].l){if(--num[a[l++]]==0)--zhi;}
while(r<q[i].r){if(++num[a[++r]]==1)++zhi;}
while(l>q[i].l){if(++num[a[--l]]==1)++zhi;}
while(r>q[i].r){if(--num[a[r--]]==0)--zhi;}//以上是普通莫队
while(now<q[i].ti)work(++now);
while(now>q[i].ti)work(now--);//以上两句是带修莫队核心
ans[q[i].poi]=zhi;
}
for(re int i=1;i<=Qnum;i++)
printf("%d\n",ans[i]);
return 0;
}