题目大意:单点修改,每次询问一个区间的所有颜色出现次数的( ext{Mex}.)
例如,区间中三种颜色分别出现了(2,2,3)次,又因为其他颜色出现次数一定是(0),所以这里的答案是(1.)
( ext{Solution:})
这是带修莫队的一道题。
观察到,我们可以(O(1))来更新一个颜色的出现次数,以及这个出现次数的次数。
套上带修莫队套路,每次按照三关键字排序,左,右,时间。时间是修改相关。每次我们更改一个颜色,就把原来的颜色删掉一个,新改的颜色加上一个就好了。
因为当块长为(n^{frac{2}{3}}.)时,时间复杂度为(n^{frac{5}{3}}).所以可以过。
下面是一些处理技巧:
对于颜色很大,观察到(n,q)不大,所以有用的颜色最多有(n+q)个,直接离散化即可。复杂度(O(nlog n).)
那么,每次答案怎么统计呢?
考虑暴力的方法。因为(0)一定不会是答案,所以我们从(1)开始枚举。考虑最长的枚举次数,设为(x).
那么有(frac{x*(x+1)}{2}leq n),就是出现次数从(1)加到(x).
那么:
(x^2+x leq 2n),也就是说(x)也就(sqrt{n})的级别左右。
如果(q)次统计,那复杂度就是(O(qsqrt n).)由于(n,q)同阶,而这个复杂度就是(O(n^{frac{3}{2}})),小于(O(n^{frac{5}{3}}).)所以复杂度有保证。
(1e5)的情况下这个复杂度还是可以的。在( ext{O2})情况下跑的很优秀。一般的话这个复杂度算出来是(O(10^{frac{25}{3}})=O(10^{8.3333})),卡时间限制可以过。
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
int bl[MAXN],a[MAXN],n,m,siz,bnum;
int ans[MAXN],cnt[MAXN],mex[MAXN];
int cntq,cntc,A[MAXN],tot,L;
inline bool isdigit(char C){return C<='9'&&C>='0';}
struct Q{
int l,r,t,id;
bool operator<(const Q&B)const{
return (bl[l]^bl[B.l])?bl[l]<bl[B.l]:(bl[r]^bl[B.r])?bl[r]<bl[B.r]:bl[t]<bl[B.t];
}
}q[MAXN];
struct C{
int pos,v;
}c[MAXN];
inline int read(){
register int s=0;
register char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
inline void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>=10)write(x/10);
putchar(x%10+48);
}
void del(int x){
--mex[cnt[a[x]]];
++mex[--cnt[a[x]]];
}
void add(int x){
--mex[cnt[a[x]]];
++mex[++cnt[a[x]]];
}
int Get(){
int i;for(i=1;mex[i];++i);
return i;
}
int main(){
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;++i)A[++tot]=read(),a[i]=A[tot];
siz=pow(n,(double)2.0/3.0);
bnum=ceil((double)n/siz);
for(register int i=1;i<=bnum;++i)for(register int j=(i-1)*siz+1;j<=i*siz;++j)bl[j]=i;
for(register int i=1;i<=m;++i){
register int opt=read();
if(opt==1){
q[++cntq].t=cntc;
q[cntq].id=cntq;
q[cntq].l=read();
q[cntq].r=read();
}
else{
c[++cntc].pos=read();
c[cntc].v=read();
A[++tot]=c[cntc].v;
}
}
sort(q+1,q+cntq+1);
sort(A+1,A+tot+1);
L=unique(A+1,A+tot+1)-A-1;
for(register int i=1;i<=n;++i)a[i]=lower_bound(A+1,A+L+1,a[i])-A;
for(register int i=1;i<=cntc;++i)c[i].v=lower_bound(A+1,A+L+1,c[i].v)-A;
int l=1,r=0,tm=0;
for(register int i=1;i<=m;++i){
int ql=q[i].l,qr=q[i].r,qt=q[i].t;
while(l<ql)del(l++);
while(l>ql)add(--l);
while(r<qr)add(++r);
while(r>qr)del(r--);
while(tm<qt){
++tm;
if(c[tm].pos>=ql&&c[tm].pos<=qr){
del(c[tm].pos);
swap(a[c[tm].pos],c[tm].v);
add(c[tm].pos);
}
if(!(c[tm].pos>=ql&&c[tm].pos<=qr))swap(a[c[tm].pos],c[tm].v);
}
while(tm>qt){
if(c[tm].pos>=ql&&c[tm].pos<=qr){
del(c[tm].pos);
swap(a[c[tm].pos],c[tm].v);
add(c[tm].pos);
}
if(!(c[tm].pos>=ql&&c[tm].pos<=qr))swap(a[c[tm].pos],c[tm].v);
--tm;
}
ans[q[i].id]=Get();
}
for(register int i=1;i<=cntq;++i)write(ans[i]),puts("");
return 0;
}