-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathdc_query_on_demand.cpp
81 lines (76 loc) · 2.31 KB
/
dc_query_on_demand.cpp
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
namespace DC {
struct range { // eh preciso definir a forma
// de calcular o range
vi freq;
ll sum = 0;
int l = 0, r = -1;
void back_l(int v) { // Mover o 'l' do range
// para a esquerda
sum += freq[v];
freq[v]++;
l--;
}
void advance_r(int v) { // Mover o 'r' do range
// para a direita
sum += freq[v];
freq[v]++;
r++;
}
void advance_l(int v) { // Mover o 'l' do range
// para a direita
freq[v]--;
sum -= freq[v];
l++;
}
void back_r(int v) { // Mover o 'r' do range
// para a esquerda
freq[v]--;
sum -= freq[v];
r--;
}
void clear(int n) { // Limpar range
l = 0;
r = -1;
sum = 0;
freq.assign(n + 5, 0);
}
} s;
vi dp_before, dp_cur;
void compute(int l, int r, int optl, int optr) {
if (l > r) return;
int mid = (l + r) >> 1;
pair<ll, int> best = {0, -1}; // {INF, -1} se quiser minimizar
while (s.l < optl) s.advance_l(v[s.l]);
while (s.l > optl) s.back_l(v[s.l - 1]);
while (s.r < mid) s.advance_r(v[s.r + 1]);
while (s.r > mid) s.back_r(v[s.r]);
vi removed;
for (int i = optl; i <= min(mid, optr); i++) {
best =
min(best,
{(i ? dp_before[i - 1] : 0) + s.sum, i}); // min() se quiser minimizar
removed.push_back(v[s.l]);
s.advance_l(v[s.l]);
}
for (int rem : removed) s.back_l(v[s.l - 1]);
dp_cur[mid] = best.first;
int opt = best.second;
compute(l, mid - 1, optl, opt);
compute(mid + 1, r, opt, optr);
}
ll solve(int n, int k) {
dp_before.assign(n, 0);
dp_cur.assign(n, 0);
s.clear(n);
for (int i = 0; i < n; i++) {
s.advance_r(v[i]);
dp_before[i] = s.sum;
}
for (int i = 1; i < k; i++) {
s.clear(n);
compute(0, n - 1, 0, n - 1);
dp_before = dp_cur;
}
return dp_before[n - 1];
}
};