2023年长沙学院程序设计竞赛(CCSUPC) H.序列MEX (分块 + bitset)
解题思路
因为总和不超过1e5,所以最多枚举到500,不知道为啥500会wa,1010就可以ac。考虑分块,每一块维护一个大小为1010的bitset。然后对于查询块外暴力,块内bitset取|,块内bitset取 | 的时间复杂度为1010 / 64。
#include <bits/stdc++.h>
const int N = 1e5 + 10;
const int M = 1010;
const int INF = 0x3f3f3f3f;
using ll = long long;
#define rep(i, x, y) for (int i = x; i <= y; i ++)
#define per(i, y, x) for (int i = y; i >= x; i --)
typedef std::pair<int, int> PII;
int n, m;
int a[N];
inline void solve() {
std::cin >> n >> m;
rep(i, 1, n) std::cin >> a[i];
int B = sqrt(n) + 1;
std::vector<std::bitset<M>> b(n / B + 1);
std::vector<std::vector<int>> cnt(n / B + 1, std::vector<int> (M, 0));
rep(i, 1, n) {
if (a[i] > M - 1) continue;
int cur = i / B;
b[cur][a[i]] = 1;
cnt[cur][a[i]] ++;
}
while (m --) {
int op, l, r, x;
std::cin >> op;
if (op == 1) {
std::cin >> l >> r;
std::bitset<M> tmp;
int lb = l / B, rb = r / B;
if (lb == rb) {
rep(i, l, r)
if (a[i] < M)
tmp[a[i]] = 1;
} else {
rep(i, l, (lb + 1) * B - 1)
if (a[i] < M)
tmp[a[i]] = 1;
rep(i, rb * B, r)
if (a[i] < M)
tmp[a[i]] = 1;
rep(i, lb + 1, rb - 1)
tmp |= b[i];
}
int ans = 0;
while (ans < M && tmp[ans]) ans ++;
std::cout << ans << '\n';
} else {
std::cin >> l >> x;
int bx = l / B;
if (a[l] < M)
if (-- cnt[bx][a[l]] == 0) b[bx][a[l]] = 0;
if (x < M)
if (++ cnt[bx][x] == 1) b[bx][x] = 1;
a[l] = x;
}
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int _ = 1;
//std::cin >> _;
while (_ --) solve();
return 0;
}