CF940F Machine Learning
题意
给定 个数的序列 ,有 次操作,每次操作有单点修改和询问区间 中每个数的出现次数的 mex。
解法
考虑莫队维护。
我们要维护 mex,并且是带修莫队,所以回滚莫队用不了。我们考虑在获得答案时暴力。
考虑维护两个数组,分别是 和 , 记录每个数出现次数, 记录每个 的出现次数。
询问答案时从 到 暴力枚举,复杂度是可以接受的。
代码:
#pragma GCC optimize("-Ofast")
#pragma GCC target("avx,sse,sse2,sse3,sse4")
#pragma unroll 10
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
const int N = 2e5 + 10;
int a[N], len, ans[N];
vector<int> b;
int n, m, cnta, cntb;
int ca[N], cb[N];
struct Query
{
int id, l, r, k;
}q[N];
struct Modify
{
int x, y;
}g[N];
inline int read()
{
register char ch = getchar();
register int x = 0;
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x;
}
inline bool cmp(const Query& x, const Query& y)
{
register int xl = x.l / len, xr = x.r / len;
register int yl = y.l / len, yr = y.r / len;
if (xl ^ yl) return xl < yl;
if (xr ^ yr) return xr < yr;
return x.k < y.k;
}
inline void add(int x)
{
--cb[ca[a[x]]];
++cb[++ca[a[x]]];
}
inline void del(int x)
{
--cb[ca[a[x]]];
++cb[--ca[a[x]]];
}
inline void change(int x, int l, int r)
{
int rem = 0;
if (g[x].x >= l && g[x].x <= r)
{
--cb[ca[a[g[x].x]]];
++cb[--ca[a[g[x].x]]];
--cb[ca[g[x].y]];
++cb[++ca[g[x].y]];
}
swap(a[g[x].x], g[x].y);
}
int main()
{
n = read();
m = read();
for (register int i = 1; i <= n; ++i)
{
a[i] = read();
b.push_back(a[i]);
}
for (register int i = 1; i <= m; ++i)
{
register int opt = read(), l = read(), r = read();
if (opt == 1)
{
++cnta;
q[cnta] = { cnta, l, r, cntb };
}
else
{
++cntb;
b.push_back(r);
g[cntb] = { l, r };
}
}
sort(b.begin(), b.end());
b.erase(unique(b.begin(), b.end()), b.end());
for (register int i = 1; i <= n; ++i)
{
a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin();
}
for (register int i = 1; i <= cntb; ++i)
{
g[i].y = lower_bound(b.begin(), b.end(), g[i].y) - b.begin();
}
len = pow(n, 2.0 / 3);
sort(q + 1, q + cnta + 1, cmp);
register int nl = 1, nr = 0, now = 0;
for (register int i = 1; i <= cnta; ++i)
{
int l = q[i].l, r = q[i].r, k = q[i].k, ansk = 0;
while (nl < l) del(nl++);
while (nl > l) add(--nl);
while (nr < r) add(++nr);
while (nr > r) del(nr--);
while (now < k) change(++now, l, r);
while (now > k) change(now--, l, r);
for (register int j = 1; ; ++j)
{
if (!cb[j])
{
ansk = j;
break;
}
}
ans[q[i].id] = ansk;
}
for (register int i = 1; i <= cnta; ++i) printf("%d\n", ans[i]);
return 0;
}

浙公网安备 33010602011771号