Problem
cf太麻烦就用洛谷
题意:给定一个数组,维护两种操作:
1、查询一段区间内的所有数字出现次数的mex
2、修改某点的值
Solution
像这种有关出现次数的多组区间询问的题目,当然蒟蒻只会用莫队啦
很明显带修改莫队,用一个桶 维护 的出现次数,用另一个桶 维护所有数字中 ,最后看 中第一个为空的即可
一开始想到动态维护 ,用堆比较方便维护,但带修莫队的复杂度 在 的数据下显得苍白无力,本来就要卡卡常,无法带一个 一起嗨皮
想到如果想法把 设为最大,则该数列至少含 个元素,由于序列长度在 的范围,则
可以将 替换为
但这样还是不能带着这个常数一起嗨
发现如果每次询问时暴力扫描,就可以不用把这个常数带在莫队上
最后离散化即可
贴一个自己容易错的地方:在设置带修莫队块的大小时
//要写成
int block = pow(n,2.0/3);
//而不是
int block = pow(n,2/3);
Code
//CF-940F
#include<algorithm>
#include<cstdio>
#include<cctype>
#include<cmath>
using namespace std;
#define rg register
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=101000;
struct Change{int p,u,v;}c[N];
int tmp[N<<1],a[N],Ans[N],blk[N];
int t1[N<<1],t2[N<<1];
int n,Q,q_;
struct node{
int l,r,id,t;
inline bool operator < (const node&bb) const {
if(blk[l]==blk[bb.l]&&blk[r]==blk[bb.r])return t<bb.t;
if(blk[l]==blk[bb.l])return blk[r]<blk[bb.r];
return blk[l]<blk[bb.l];
}
}q[N];
int main(){
read(n);read(Q);rg int now=(0);
for(rg int i=1;i<=n;++i)tmp[++tmp[0]]=read(a[i]);
for(rg int i=1,opt;i<=Q;++i){
read(opt);
if(opt==1){
++q_;read(q[q_].l);read(q[q_].r);
q[q_].t=now;q[q_].id=q_;
}else {
++now;read(c[now].p);
tmp[++tmp[0]]=read(c[now].v);
}
}
sort(tmp+1,tmp+tmp[0]+1);
int tmplen=unique(tmp+1,tmp+tmp[0]+1)-tmp-1;
for(rg int i=1;i<=n;++i)a[i]=lower_bound(tmp+1,tmp+tmplen+1,a[i])-tmp;
for(rg int i=1;i<=now;++i)c[i].v=lower_bound(tmp+1,tmp+tmplen+1,c[i].v)-tmp;
int block=pow(n,2.0/3);
for(rg int i=1;i<=n;++i)blk[i]=(i-1)/block+1;
sort(q+1,q+q_+1);
for(rg int i=1;i<=now;++i){
c[i].u=a[c[i].p];
a[c[i].p]=c[i].v;
}
rg int l=1,r=0,t=now;
for(rg int i=1;i<=q_;++i){
while(t<q[i].t){
++t;
if(l<=c[t].p&&c[t].p<=r){
--t2[t1[c[t].u]],
--t1[c[t].u],
++t2[t1[c[t].u]],
--t2[t1[c[t].v]],
++t1[c[t].v],
++t2[t1[c[t].v]];
}
a[c[t].p]=c[t].v;
}
while(q[i].t<t){
if(l<=c[t].p&&c[t].p<=r){
--t2[t1[c[t].v]],
--t1[c[t].v],
++t2[t1[c[t].v]],
--t2[t1[c[t].u]],
++t1[c[t].u],
++t2[t1[c[t].u]];
}
a[c[t].p]=c[t].u,--t;
}
while(q[i].l<l){--l,--t2[t1[a[l]]],++t1[a[l]],++t2[t1[a[l]]];}
while(r<q[i].r){++r,--t2[t1[a[r]]],++t1[a[r]],++t2[t1[a[r]]];}
while(l<q[i].l){--t2[t1[a[l]]],--t1[a[l]],++t2[t1[a[l]]],++l;}
while(q[i].r<r){--t2[t1[a[r]]],--t1[a[r]],++t2[t1[a[r]]],--r;}
for(rg int j=1;;++j)if(!t2[j]){Ans[q[i].id]=j;break;}
}
for(rg int i=1;i<=q_;++i)printf("%d\n",Ans[i]);
return 0;
}