CF 1436E Complicated Computations
阿新 • • 發佈:2021-01-20
- 有長度為 \(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; }