CF 1436E Complicated Computations

  • 有长度为 \(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;
}
上一篇:C# Halcon联合编程问题(二)


下一篇:GYM102119A Tritwise Mex