[CF1476G] Minimum Difference
不显然不同出现次数的数最多 \(O \left ( \sqrt n \right )\)。
\(\sum\limits_{i=1}^k i = n\)
算出 \(k\) 最大为 \(\sqrt n\)。
则莫队 + 值域分块,维护每个出现次数有几个数。
查询时扫所有块,块内有值就暴力整块,把所有有值的位置提出来,做双指针。
具体一点,设当前双指针的左右端点分别为 \(l, r\)。
不断循环直到 \(\left [ l, r \right ]\) 总的出现次数大于等于 \(k\)。
然后每次把 \(l\) 往后移一位就行。
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int f = 0, ans = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
return f ? -ans : ans;
}
void write(int x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
constexpr int N = 1e5 + 5, V = 1e5, inf = 1e9;
int n, m, a[N], res[N];
int blk, l, r, bl[N], mp[N];
struct oper
{
int p, lst, x;
} op[N];
struct quest
{
int l, r, k, tim, id;
bool operator<(const quest &rhs) const
{
if (bl[l] != bl[rhs.l])
return l < rhs.l;
if (bl[r] != bl[rhs.r])
return r < rhs.r;
return tim < rhs.tim;
}
} q[N];
namespace block
{
int blk, tot, bl[N], L[N], R[N];
int t, s[N], cnt[N], cnt_blk[N];
inline void init()
{
blk = pow(V, 2.0 / 3);
tot = V / blk + (bool)(V % blk);
for (int i = 1; i <= V; ++i)
bl[i] = (i - 1) / blk + 1;
for (int i = 1; i <= tot; ++i)
L[i] = (i - 1) * blk + 1, R[i] = i * blk;
R[tot] = V;
}
inline void modify(int x, int w) { x ? (cnt[x] += w, cnt_blk[bl[x]] += w) : 0; }
inline int get_ans(int k)
{
t = 0;
for (int i = 1; i <= tot; ++i)
if (cnt_blk[i])
for (int j = L[i]; j <= R[i]; ++j)
if (cnt[j])
s[++t] = j;
int ans = inf, sum = 0;
for (int l = 1, r = 0; l <= t; ++l)
{
while (r < t && sum < k)
sum += cnt[s[++r]];
if (sum < k)
break;
ans = min(ans, s[r] - s[l]);
sum -= cnt[s[l]];
}
return ans;
}
}
inline void init()
{
block::init(), blk = pow(n, 2.0 / 3);
for (int i = 1; i <= n; ++i)
bl[i] = (i - 1) / blk + 1;
}
inline void insert(int x) { block::modify(mp[x], -1), block::modify(++mp[x], 1); }
inline void remove(int x) { block::modify(mp[x], -1), block::modify(--mp[x], 1); }
inline void insert_in_bound(int i)
{
if (i >= l && i <= r)
block::modify(mp[a[i]], -1), block::modify(++mp[a[i]], 1);
}
inline void remove_in_bound(int i)
{
if (i >= l && i <= r)
block::modify(mp[a[i]], -1), block::modify(--mp[a[i]], 1);
}
inline void forward(int i)
{
auto &[p, lst, x] = op[i];
remove_in_bound(p);
a[p] = x;
insert_in_bound(p);
}
inline void backward(int i)
{
auto &[p, lst, x] = op[i];
remove_in_bound(p);
a[p] = lst;
insert_in_bound(p);
}
signed main()
{
// freopen("chk.in", "r", stdin);
// freopen("chk.out", "w", stdout);
n = read(), m = read();
for (int i = 1; i <= n; ++i)
a[i] = read();
init();
int que = 0, ti = 0;
for (int i = 1; i <= m; ++i)
if (read() == 1)
{
++que, q[que] = {0, 0, 0, ti, que};
q[que].l = read(), q[que].r = read(), q[que].k = read();
}
else
{
++ti;
op[ti].lst = a[op[ti].p = read()];
a[op[ti].p] = op[ti].x = read();
}
while (ti)
a[op[ti].p] = op[ti].lst, --ti;
sort(q + 1, q + que + 1);
l = 1, r = 0;
for (int i = 1; i <= que; ++i)
{
while (l > q[i].l)
insert(a[--l]);
while (r < q[i].r)
insert(a[++r]);
while (l < q[i].l)
remove(a[l++]);
while (r > q[i].r)
remove(a[r--]);
while (ti < q[i].tim)
forward(++ti);
while (ti > q[i].tim)
backward(ti--);
res[q[i].id] = block::get_ans(q[i].k);
}
for (int i = 1; i <= que; ++i)
write(res[i] == inf ? -1 : res[i]), putchar('\n');
return 0;
}

浙公网安备 33010602011771号