About the interval \ (mex \) several practices
Subject to the effect
In seeking \ (SG \) mentioned a function through a \ (MEX \) function;
\ (MEX (\ {a_i \}) \) represents the \ (A \) minimum natural number not appearing, where \ (a_i \ in \ N \) .
To a length \ (n-\) sequence \ (A \) , \ (m \) queries, each query \ (mex (\ {a_i \ }), i \ in [l, r] \)
1, Mo + team Fenwick tree
Fenwick tree to maintain each of the weights number of occurrences;
Complexity: \ (O (m \ sqrt n-logN) \)
2, Mo + team block
The weight sub-blocks, each block maintains the number appeared a few;
Complexity: $ O ((n + m ) \ sqrt n);
code as follows:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
const int N = 2e5 + 5;
int blo, bl[N];
struct query {
int l, r, id;
} q[N];
int n, m;
int a[N], res[N];
inline bool cmp (const query &i, const query &j) {
if (bl[i.l] != bl[j.l])
return bl[i.l] < bl[j.l];
if (bl[i.l] & 1)
return i.r < j.r;
return i.r > j.r;
}
struct block_split {
int a[N], b[1000];
inline void modify(int p, int k) {
if (!a[p])
++b[bl[p]];
a[p] += k;
if (!a[p])
--b[bl[p]];
}
int query() {
int i;
for (i = 1; i < bl[n]; ++i)
if (b[i] < blo)
break;
for (int j = (i - 1) * blo; j <= std::min(n, i * blo - 1); ++j)
if (!a[j])
return j;
return n;
}
} B;
inline void add(const int p) {
B.modify(a[p], 1);
}
inline void rem(const int p) {
B.modify(a[p], -1);
}
int main() {
n = in(), m = in();
for (int i = 1; i <= n; ++i)
a[i] = in(), chk_min(a[i], n);
for (int i = 1; i <= m; ++i)
q[i] = (query){in(), in(), i};
blo = (int)sqrt(n + 1);
for (int i = 0; i <= n; ++i)
bl[i] = i / blo + 1;
std::sort(q + 1, q + 1 + m, cmp);
for (int i = 1, l = 1, r = 0; i <= m; ++i) {
for (; l > q[i].l; add(--l));
for (; r < q[i].r; add(++r));
for (; l < q[i].l; rem(l++));
for (; r > q[i].r; rem(r--));
res[q[i].id] = B.query();
}
for (int i = 1; i <= m; ++i)
printf("%d\n", res[i]);
return 0;
}
3, the Chairman of the tree
The above approach to offline, Chairman of the tree can handle online inquiries, and the complexity of the more outstanding.
Chairman of the tree maintenance each number in the first \ (i \) position before a version of history, the last occurrence.
For a set of query \ (L, r \) , the first \ (r \) to find the last time in the history of th edition \ (l \) the minimum number of pre-historic version.
code show as below:
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x;
}
const int N = 2e5 + 5;
struct persistable_tree {
int min[20 * N], rt[20 * N], c[20 * N][2];
int tot;
void modify(int pos, int k, int tl, int tr, int pre, int &p) {
p = ++tot;
if (tl == tr)
return (void)(min[p] = k);
c[p][0] = c[pre][0], c[p][1] = c[pre][1];
int mid = (tl + tr) >> 1;
if (mid >= pos)
modify(pos, k, tl, mid, c[pre][0], c[p][0]);
else
modify(pos, k, mid + 1, tr, c[pre][1], c[p][1]);
min[p] = std::min(min[c[p][0]], min[c[p][1]]);
}
int query(int k, int tl, int tr, int p) {
if (tl == tr)
return tl;
int mid = (tl + tr) >> 1;
if (min[c[p][0]] < k)
return query(k, tl, mid, c[p][0]);
else
return query(k, mid + 1, tr, c[p][1]);
}
} T;
int main() {
int n = in(), m = in();
for (int i = 1, x; i <= n; ++i) {
x = in();
T.modify(x, i, 0, n, T.rt[i - 1], T.rt[i]);
}
int l, r;
while (m--) {
l = in(), r = in();
printf("%d\n", T.query(l, 0, n, T.rt[r]));
}
return 0;
}