题目
有一个长度为nnn的数组[a1,a2,...,an][a1,a2,...,an][a1,a2,...,an]。mmm次询问,每次询问一个区间内最小没有出现过的自然数。
分析
其实这道题出的不算很好,因为即使a≤109a\leq 10^9a≤109,也只是纸老虎,因为一共才不超过2×1052\times 10^52×105个数,嗯,所以其实并没有什么用,只要把超过nnn的数都变成n+1n+1n+1就可以了,然后既然离线,就直接莫队就可以了 (我知道正解是主席树)
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#define rr register
using namespace std;
struct rec{int l,r,rk;}b[200001];
int n,m,bk,cnt[200011],a[200001],ans,answ[200001];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
bool cmp(rec x,rec y){
if (x.l/bk!=y.l/bk) return x.l/bk<y.l/bk;
return x.r<y.r;
}
inline void del(int x){
if (!(--cnt[a[x]])&&ans>a[x]) ans=a[x];
}
inline void add(int x){
if ((++cnt[a[x]])==1){
rr int tmp=a[x];
if (ans==tmp)
while (++tmp){
if (!cnt[tmp]) {ans=tmp; return;}
}
}
}
signed main(){
n=iut(); m=iut(); bk=pow(n,9.0/17);
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=1;i<=n;++i) if (a[i]>n) a[i]=n+1;
for (rr int i=1;i<=m;++i) b[i]=(rec){iut(),iut(),i};
sort(b+1,b+1+m,cmp);
rr int l=b[1].l,r=b[1].l-1;
for (rr int i=1;i<=m;++i){
while (l>b[i].l) add(--l);
while (l<b[i].l) del(l++);
while (r<b[i].r) add(++r);
while (r>b[i].r) del(r--);
answ[b[i].rk]=ans;
}
for (rr int i=1;i<=m;++i) printf("%d\n",answ[i]);
return 0;
}