- 有长度为 \(n\le 1e5\) 的序列,求出它的所有子区间的 \(mex\) 值构成的集合的 \(mex\) 值。
先求出每个 \(mex\) 值是否出现过,再扫一遍输出即可。
每个值 \(v\) 能成为 \(mex\),必须满足存在区间 \(l...r\) 使得 \(1...v-1\) 全部出现,且 \(v\) 不在其中,于是若干个 \(v\) 将区间分为若干个块,需要判断每个块中 \(1...v-1\) 是否全部出现过。可以扫一遍序列,维护当前每个元素出现的最晚位置,判断 \(1...v-1\) 的最早的最晚位置是否在前一个 \(v\) 位置以后即可。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
#define fi first
#define se second
typedef long long LL;
typedef pair <int, int> P;
const int inf = 0x3f3f3f3f, mod = 1e9 + 7, N = 3e5 + 10;
template <typename T>
inline void rd_(T &x) {
x = 0; int f = 1;
char ch = getchar();
while (ch > '9' || ch < '0') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = x*10 + ch - '0', ch = getchar();
x *= f;
}
int n, x, mi[N<<2], last[N];
bool vis[N];
void update_(int o, int l, int r, int x, int k) {
if (l == r) {
mi[o] = k;
return;
}
int mid = (l + r)>>1;
if (x <= mid) update_(o<<1, l, mid, x, k);
else update_(o<<1|1, mid + 1, r, x, k);
mi[o] = min(mi[o<<1], mi[o<<1|1]);
}
int query_(int o, int l, int r, int x, int y) {
if (x <= l && r <= y) return mi[o];
int mid = (l + r)>>1, res = inf;
if (x <= mid) res = min(res, query_(o<<1, l, mid, x, y));
if (mid < y) res = min(res, query_(o<<1|1, mid + 1, r, x, y));
return res;
}
int main() {
rd_(n);
rep (i, 1, n) {
rd_(x);
if (x == 1) vis[x] = max(vis[x], last[x] != i - 1);
else vis[x] = max(vis[x], query_(1, 1, n, 1, x - 1) > last[x]);
update_(1, 1, n, x, last[x] = i);
}
vis[1] = max(vis[1], last[1] != n);
rep (i, 2, n + 1)
vis[i] = max(vis[i], query_(1, 1, n, 1, i - 1) > last[i]);
rep (i, 1, n + 2)
if (!vis[i]) return printf("%d\n", i), 0;
}