Description
有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
Input
第一行n,m。
第二行为n个数。
从第三行开始,每行一个询问l,r。
Output
一行一个数,表示每个询问的答案。
Examples
Sample Input
5 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
Sample Output
1
2
3
0
3
Note
1
≤
n
,
m
≤
200000
1 \leq n,m \leq 200000
1≤n,m≤200000
0 ≤ a i ≤ 1 0 9 0 \leq a_i \leq 10^9 0≤ai≤109
1 ≤ l ≤ r ≤ n 1 \leq l \leq r \leq n 1≤l≤r≤n
Solution
本题有多种解法,这里考虑莫队 + 分块
对权值分块,用莫队维护当前询问区间的每个数字出现次数以及每个块内出现的数字种数
每次暴力找到第一个没满的块,再进去暴力找到没出现的最小数字
复杂度
O
(
n
n
)
O(n\sqrt{n})
O(nn)
Code
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define re register
using namespace std;
const int maxn = 2e5 + 5;
inline int read() {
int num = 0, F = 1; char c = ' ';
while (c < '0' || c > '9') F = (c == '-') ? -1 : 1, c = getchar();
while (c >= '0' && c <= '9') num = (num << 1) + (num << 3) + c - '0', c = getchar();
return num * F;
}
void print(int x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
int n,m,blksiz, maxblk;
int a[maxn],blk[maxn], le[maxn],ri[maxn];
struct Query{
int l,r,id,v;
}q[maxn];
bool cmp(Query x, Query y){return (x.v == y.v) ? (x.v&1) ? x.r < y.r : x.r > y.r : x.l < y.l;}
int cnt[maxn], bnum[maxn], siz[maxn];
inline void add(int pos){if(++cnt[a[pos]] == 1) bnum[blk[a[pos]]]++;}
inline void del(int pos){if(--cnt[a[pos]] == 0) bnum[blk[a[pos]]]--;}
int ans[maxn];
inline int get_ans(){
for(re int i = 1;i <= maxblk;++i){
if(siz[i] != bnum[i]){
for(int j = le[i];j <= ri[i];++j) if(!cnt[j]) return j;
}
}
return n;
}
int main(){
n = read(), m = read();
blksiz = (int)sqrt((double)n);
for(re int i = 1;i <= n;++i){
a[i] = read();
if(a[i] > n) a[i] = n + 1;
}
for(re int i = 0;i <= n;++i){
blk[i] = i / blksiz + 1;
}
maxblk = blk[n];
for(re int i = 1;i <= maxblk;++i){
le[i] = (i-1) * blksiz;
ri[i] = i * blksiz - 1;
siz[i] = ri[i] - le[i] + 1;
}
ri[maxblk] = n, siz[maxblk] = ri[maxblk] - le[maxblk] + 1;
for(re int i = 1;i <= m;++i){
q[i].l = read(), q[i].r = read();
q[i].id = i, q[i].v = blk[q[i].l];
} sort(q + 1,q + 1 + m,cmp);
for(re int i = 1, curL = 1, curR = 0;i <= m;++i){
int L = q[i].l, R = q[i].r, id = q[i].id;
while(curL < L) del(curL++);
while(curL > L) add(--curL);
while(curR > R) del(curR--);
while(curR < R) add(++curR);
ans[id] = get_ans();
}
for(re int i = 1;i <= m;++i){
print(ans[i]);puts("");
}
return 0;
}