CF 1476G Minimum Difference

题目描述

https://codeforces.com/contest/1476/problem/G

Solution

考虑带修莫队,注意到不同的 $cnt_i$ 最多有 $O(\sqrt n)$ 个

所以我们用链表从小到大连接起来,然后再查询的时候暴力即可

时间复杂度 $O(n^{\frac{5}{3}})$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define maxn 100010
using namespace std;

int n, m, a[maxn];

int c1, c2, blo;
struct Query {
int l, r, t, k, id;

friend bool operator < (const Query &u, const Query &v) {
if (u.l / blo != v.l / blo) return u.l < v.l;
if (u.r / blo != v.r / blo) return u.r < v.r;
return u.k < v.k;
}
} Q[maxn];

struct Modify {
int k, v;
} C[maxn];

int pre[maxn], nxt[maxn], d[maxn], cnt[maxn];
inline void add(int v) {
int p = cnt[v], n = cnt[v] + 1; ++cnt[v];
if (--d[p] == 0) {
nxt[pre[p]] = nxt[p];
pre[nxt[p]] = pre[p];
p = pre[p];
}
if (++d[n] == 1) {
pre[n] = p; nxt[n] = nxt[p];
pre[nxt[p]] = n; nxt[p] = n;
}
}

inline void del(int v) {
int n = cnt[v], p = cnt[v] - 1; --cnt[v];
if (--d[n] == 0) {
nxt[pre[n]] = nxt[n];
pre[nxt[n]] = pre[n];
n = nxt[n];
}
if (++d[p] == 1) {
nxt[p] = n; pre[p] = pre[n];
nxt[pre[n]] = p; pre[n] = p;
}
}

inline void modify(int i, int l, int r) {
if (l <= C[i].k && C[i].k <= r)
del(a[C[i].k]), add(C[i].v);
swap(a[C[i].k], C[i].v);
}

int query(int k) {
int i = nxt[0], j = nxt[0], ans = n + 1, s = 0, cnt = 0;
while (i != n + 1) {
while (j != n + 1 && s < k) s += d[j], j = nxt[j];
if (s >= k) ans = min(ans, pre[j] - i);
s -= d[i]; i = nxt[i];
if (++cnt >= n) exit(-1);
}
if (ans == n + 1) return -1;
return ans;
}

int ans[maxn], cans;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);

cin >> n >> m; blo = pow(n, 0.66666);
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= m; ++i) {
int opt, x, y, z; cin >> opt >> x >> y;
if (opt == 1) cin >> z, Q[++c1] = { x, y, z, c2, ++cans };
else C[++c2] = { x, y };
}
sort(Q + 1, Q + c1 + 1); d[0] = n + 1; nxt[0] = n + 1; pre[n + 1] = 0;
int l = Q[1].l, r = l - 1, k = 0;
for (int i = 1; i <= c1; ++i) {
while (r < Q[i].r) add(a[++r]);
while (l > Q[i].l) add(a[--l]);
while (r > Q[i].r) del(a[r--]);
while (l < Q[i].l) del(a[l++]);
while (k < Q[i].k) modify(++k, l, r);
while (k > Q[i].k) modify(k--, l, r);
ans[Q[i].id] = query(Q[i].t);
}
for (int i = 1; i <= cans; ++i) cout << ans[i] << "\n";
return 0;
}