题意:支持两种操作:$1.$ 查询 $[l,r]$ 每个数字出现次数的 $mex$,$2.$ 单点修改某一位置的值.
这里复习一下带修改莫队.
普通的莫队中,以左端点所在块编号为第一关键字,右端点大小为第二关键字,在带修改莫队中每一个操作都有一个时间戳,那时间戳就是第三关键字.
可以将数字先离散化,开一个桶来维护每一种数字出现的次数.
然后在移动区间时就将对应数字删除/插入.
再维护一个当前时刻,表示当前数组的状态是第 $now$ 个修改进行后的状态.
将 $now$ 一直移动到和当前询问的时间戳吻合即可.
注意:在移动时间戳的时候要换一下修改的值. 假如说原来的修改是变成 $y$,而序列中的元素为 $x$,就要将修改的元素变成 $y$.
这样在下一次经过这个时间戳的时候就会将之前改动过的值再改回来.
排序函数一定要注意:
struct query { int l,r,id,t; query(int l=0,int r=0):l(l),r(r){} bool operator<(query b) const { return l/B==b.l/B?(r/B==b.r/B?t<b.t:r<b.r):l<b.l; } }q[N];
这里千万不能写错,否则整个时间复杂度就假了~
一般来说,带修改莫队中块的大小取在 $n^{0.6666}$ 来说是比较优的.
这道题中,你发现 $mex$ 的大小不超过 $sqrt n$,所以我们可以直接暴力求.
code:
#include <bits/stdc++.h> #define N 300005 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,m,tot,opcnt,qcnt,B,now; int a[N],A[N],output[N],cnt[N],mex[N]; struct query { int l,r,id,t; query(int l=0,int r=0):l(l),r(r){} bool operator<(query b) const { return l/B==b.l/B?(r/B==b.r/B?t<b.t:r<b.r):l<b.l; } }q[N]; struct change { int p,x; change(int p=0,int x=0):p(p),x(x){} }c[N]; void add(int num) { --mex[cnt[num]]; ++mex[++cnt[num]]; } void del(int num) { --mex[cnt[num]]; ++mex[--cnt[num]]; } void update(int id,int t) { if(c[t].p>=q[id].l&&c[t].p<=q[id].r) { del(a[c[t].p]); add(c[t].x); } swap(c[t].x, a[c[t].p]); } int getans() { int i,j; for(i=1;mex[i]>0;++i); return i; } int main() { int i,j,l=2,r=1; // setIO("input"); scanf("%d%d",&n,&m); B=pow(n,0.6666); for(i=1;i<=n;++i) { scanf("%d",&a[i]); A[++tot]=a[i]; } for(i=1;i<=m;++i) { int op,a,b; scanf("%d%d%d",&op,&a,&b); if(op==1) { ++qcnt; q[qcnt]=query(a,b); q[qcnt].id=qcnt; q[qcnt].t=opcnt; } else { ++opcnt; c[opcnt]=change(a,b); A[++tot]=b; } } sort(A+1,A+1+tot); for(i=1;i<=n;++i) a[i]=lower_bound(A+1,A+1+tot,a[i])-A; for(i=1;i<=opcnt;++i) c[i].x=lower_bound(A+1,A+1+tot,c[i].x)-A; sort(q+1,q+1+qcnt); for(i=1;i<=qcnt;++i) { for(;l>q[i].l;) add(a[--l]); for(;r<q[i].r;) add(a[++r]); for(;l<q[i].l;) del(a[l++]); for(;r>q[i].r;) del(a[r--]); for(;now<q[i].t;) update(i, ++now); for(;now>q[i].t;) update(i, now--); output[q[i].id]=getans(); } for(i=1;i<=qcnt;++i) printf("%d ",output[i]); return 0; }