Luogu P4137 Rmq Problem/mex
这题可以用莫队做~
先套一波莫队模板,然后我们可以用时间复杂度有时O(n)有时O(1)的的转移操作把这题卡过去qwq……
先复习一遍莫队模板:莫队模板戳这里qwq
我们看到数据范围:$0 \leq a_i \leq 10^9$,很显然我们这个数据不能直接开个数组来统计每个数出现的次数,但我们也知道,取$mex$时有很多数据是没有用的,比如那些大于$n$的数,这些数并不会影响我们的结果,所以我们可以直接排除掉他们。所以计数器数组只需开到$n$就可以了。
然后就是莫队模板啦~
var n,m,i,j,k,x,y,ans:longint; a,b,l,r,num,an:array[0..200000]of longint; function check(x1,y1,x2,y2:longint):boolean; begin if (trunc(x1/sqrt(n))>trunc(y1/sqrt(n)))or(trunc(x1/sqrt(n))=trunc(y1/sqrt(n)))and(x2>y2) then exit(true) else exit(false); end; procedure sort(ll,rr:longint); var i,j,x,y,z:longint; begin i:=ll; j:=rr; x:=l[(ll+rr) div 2]; z:=r[(ll+rr) div 2]; repeat while check(l[i],x,r[i],z) do inc(i); while check(x,l[j],z,r[j]) do dec(j); if not(i>j) then begin y:=l[i]; l[i]:=l[j]; l[j]:=y; y:=r[i]; r[i]:=r[j]; r[j]:=y; y:=num[i]; num[i]:=num[j]; num[j]:=y; inc(i); dec(j); end; until i>j; if ll<j then sort(ll,j); if i<rr then sort(i,rr); end; begin readln(n,m); for i:=1 to n do read(a[i]); for i:=1 to m do begin readln(l[i],r[i]); num[i]:=i; end; sort(1,m); for i:=l[1] to r[1] do if a[i]<=n then//排除大于n的值 inc(b[a[i]]); for i:=0 to n do if b[i]=0 then begin an[num[1]]:=i;//num:答案编号;an:答案 ans:=i;//ans记录当前最先找到的没有出现过的自然数 break; end; x:=l[1]; y:=r[1]; for i:=2 to m do begin while x>l[i] do//左端点向左扩张 begin dec(x); if a[x]>n then//值大于n就跳过 continue; inc(b[a[x]]); if a[x]=ans then//如果当前扩张到的值就是最小值 for j:=ans+1 to n do//继续往后搜最小值 if b[j]=0 then begin ans:=j; break; end; end; while y<r[i] do//右端点向右扩张 begin inc(y); if a[y]>n then//值大于n就跳过 continue; inc(b[a[y]]); if a[y]=ans then//如果当前扩张到的值就是最小值 for j:=ans+1 to n do//继续往后搜最小值 if b[j]=0 then begin ans:=j; break; end; end; while x<l[i] do//左端点向右收缩 begin if a[x]>n then//值大于n就跳过 begin inc(x); continue; end; dec(b[a[x]]); if (b[a[x]]=0)and(a[x]<ans) then//如果当前收缩的值剩余个数为0且为最小值 ans:=a[x];//记为最小值 inc(x); end; while y>r[i] do//右端点向左收缩 begin if a[y]>n then//值大于n就跳过 begin dec(y); continue; end; dec(b[a[y]]); if (b[a[y]]=0)and(a[y]<ans) then//如果当前收缩的值剩余个数为0且为最小值 ans:=a[y];//记为最小值 dec(y); end; an[num[i]]:=ans; end; for i:=1 to m do writeln(an[i]); end.