Skip to content

Commit 0873098

Browse files
committed
Respond to PR comments
1 parent 1e1f1a1 commit 0873098

File tree

7 files changed

+94
-98
lines changed

7 files changed

+94
-98
lines changed

_includes/source_code/code/37-PDP/tiphunting/TASK

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,31 @@ TASK(
1313
passes_only = [2, 3, 4, 5],
1414
lang = "c++",
1515
),
16-
SOLUTION(
16+
SOLUTION(
1717
name = "subtask2",
1818
source = "subtask2.cc",
1919
passes_only = [6, 7, 8, 9, 10],
2020
lang = "c++",
2121
),
22-
SOLUTION(
22+
SOLUTION(
2323
name = "subtask3",
2424
source = "subtask3.cc",
2525
passes_only = [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
2626
lang = "c++",
2727
),
28-
SOLUTION(
28+
SOLUTION(
2929
name = "subtask4",
3030
source = "subtask4.cc",
3131
passes_only = [6, 7, 8, 9, 10, 16, 17, 18, 19, 20, 21],
3232
lang = "c++",
3333
),
34-
SOLUTION(
34+
SOLUTION(
3535
name = "subtask5",
3636
source = "subtask5.cc",
3737
passes_only = [22, 23, 24, 25, 26, 27],
3838
lang = "c++",
3939
),
40-
SOLUTION(
40+
SOLUTION(
4141
name = "subtask6",
4242
source = "optimal.cc",
4343
passes_all,

_includes/source_code/code/37-PDP/tiphunting/optimal.cc

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@ vector<long long> subtree_loop_opt, supertree_loop_opt, supertree_root_opt;
1818

1919
long long positive_part(long long x) { return max(0LL, x); }
2020

21+
// Αρχικοποίηση όλων των global vectors για ένα δέντρο με `n` κορυφές.
22+
void init(int n) {
23+
// ceil(log2(max_N))
24+
constexpr int kMaxH = 18;
25+
26+
tip.resize(n);
27+
tree.resize(n);
28+
29+
// Αρχικοποιώντας `depth[0] = 0`, `parent[0] = 0` θέτουμε την κορυφή
30+
// 0 ως ρίζα του δέντρου. Η συνάρτηση `compute_auxiliary` συμπληρώνει
31+
// τις τιμές και για τους υπόλοιπους κόμβους.
32+
depth.resize(n, 0);
33+
parent.resize(n, 0);
34+
parent_weight.resize(n, 0);
35+
36+
pred.resize(kMaxH, vector<long>(n));
37+
subtree_loop_opt.resize(n);
38+
supertree_loop_opt.resize(n);
39+
supertree_root_opt.resize(n);
40+
}
41+
2142
// Διασχίζει το δέντρο `tree` ξεκινώντας από την κορυφή `u` και υπολογίζει
2243
// αναδρομικά τις τιμές `depth[v]`, `parent[v]` και `parent_weight[v]` για κάθε
2344
// κορυφή `v != u` στο υποδέντρο της `u`. Οι τιμές `depth[u]`, `parent[u]` και
@@ -108,8 +129,9 @@ void compute_supertree_loop_opt(int u) {
108129
// O caller θα πρέπει να έχει ήδη υπολογίσει τον πίνακα parent
109130
// (δες `compute_auxiliary`) έτσι ώστε η τιμή `parent[u]` να είναι
110131
// ο γονέας της `u`, εκτός από την ρίζα `r` για την οποία `r == parent[r]`.
111-
void compute_pred(long H) {
132+
void compute_pred() {
112133
const long n = parent.size();
134+
const long H = pred.size() - 1;
113135

114136
for (long u = 0; u < n; ++u)
115137
pred[0][u] = parent[u];
@@ -147,7 +169,7 @@ lll lca(long u, long v) {
147169
if (pred[0][u] == v)
148170
return { v, u, -1 };
149171

150-
u =pred[0][u];
172+
u = pred[0][u];
151173
}
152174

153175
for (long h = H; h >= 0; --h) {
@@ -167,14 +189,14 @@ int main() {
167189
long n, q;
168190
scanf("%li%li", &n, &q);
169191

170-
tip.resize(n);
192+
init(n);
193+
171194
for (long i = 0; i < n; ++i)
172195
scanf("%li", &tip[i]);
173196

174197
// Αναπαράσταση του δέντρου με adjacency list:
175198
// To `tree[u]` περιέχει ένα vector με pairs `(v, w)` για κάθε κορυφή `v` που
176199
// συνδέεται με τη `u` με κόστός `w`.
177-
tree.resize(n);
178200
for (long i = 0; i < n-1; ++i) {
179201
long u, v, w;
180202
scanf("%li%li%li", &u, &v, &w);
@@ -183,41 +205,18 @@ int main() {
183205
tree[v-1].push_back({u-1, w});
184206
}
185207

186-
// Αρχικοποιώντας `depth[0] = 0`, `parent[0] = 0` θέτουμε την κορυφή
187-
// 0 ως ρίζα του δέντρου. Η συνάρτηση `compute_auxiliary` συμπληρώνει
188-
// τις τιμές και για τους υπόλοιπους κόμβους.
189-
depth.resize(n, 0);
190-
parent.resize(n, 0);
191-
parent_weight.resize(n, 0);
192208
compute_auxiliary(0);
193209

194-
// Θα χρειαστούμε το μέγιστο βάθος ώστε να υπολογίσουμε τις διαστάσεις
195-
// πίνακα `pred` παρακάτω.
196-
long max_depth = 0;
197-
for (long i = 0; i < n; ++i)
198-
max_depth = max(max_depth, depth[i]);
199-
200-
// Υπολογισμός του πίνακα `pred` από τον πίνακα `parent`.
201-
// Το δέντρο έχει ύψος `max_depth` επομένως θα χρειαστούμε τους
202-
// απογόνους (predecessors) το πολύ μέχρι `max_depth <= 2^H` επίπεδα παραπάνω.
203-
const long H = long(ceil(log2(max_depth)));
204-
pred.resize(H+1, vector<long>(n, 0));
205-
compute_pred(H);
210+
compute_pred();
206211

207-
subtree_loop_opt.resize(n);
208212
compute_subtree_loop_opt(0);
209-
210-
supertree_loop_opt.resize(n);
211213
compute_supertree_loop_opt(0);
212-
213-
supertree_root_opt.resize(n);
214214
compute_supertree_root_opt(0);
215215

216216
for (long i = 0; i < q; ++i) {
217217
long L, R;
218218
scanf("%li%li", &L, &R);
219-
L -= 1;
220-
R -= 1;
219+
L--, R--;
221220

222221
if (L == R) {
223222
printf("%lli\n", subtree_loop_opt[L] + supertree_loop_opt[L]);
@@ -241,22 +240,13 @@ int main() {
241240
assert(pred[0][u] == z);
242241
assert(pred[0][v] == z);
243242

244-
// (a)
245-
sol = supertree_root_opt[L] - supertree_root_opt[u] + subtree_loop_opt[L] ;
246-
247-
// (b)
248-
sol += supertree_root_opt[R] - supertree_root_opt[v] + subtree_loop_opt[R];
249-
250-
// (c)
251-
sol += subtree_loop_opt[z];
252-
sol -= positive_part(subtree_loop_opt[u] - 2*parent_weight[u]);
253-
sol -= positive_part(subtree_loop_opt[v] - 2*parent_weight[v]);
254-
255-
// (d)
256-
sol += supertree_loop_opt[z];
257-
258-
// (e)
259-
sol -= (parent_weight[u] + parent_weight[v]);
243+
sol = supertree_root_opt[L] - supertree_root_opt[u] + subtree_loop_opt[L] // (a)
244+
+ supertree_root_opt[R] - supertree_root_opt[v] + subtree_loop_opt[R] // (b)
245+
+ subtree_loop_opt[z] // (c1)
246+
- positive_part(subtree_loop_opt[u] - 2*parent_weight[u]) // (c2)
247+
- positive_part(subtree_loop_opt[v] - 2*parent_weight[v]) // (c3)
248+
+ supertree_loop_opt[z] // (d)
249+
- (parent_weight[u] + parent_weight[v]); // (e)
260250
}
261251

262252
printf("%lli\n", sol);

_includes/source_code/code/37-PDP/tiphunting/subtask2.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ vl tip;
1313

1414
long long positive_part(long long x) { return max(0LL, x); }
1515

16-
// Επιστρέφει το κέρδος της βέλτιστης διαδρομή η οποία ξεκινάει
16+
// Επιστρέφει το κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
1717
// από την κορυφή `u`, καταλήγει πίσω σε αυτή και παραμένει
18-
// εξ' ολοκλήρου μέσα στο υποδέντρο που ορίζει η `u` -- με άλλα λόγια,
18+
// εξ' ολοκλήρου μέσα στο υποδέντρο που ορίζει η `u`. Με άλλα λόγια,
1919
// η διαδρομή απαγορεύεται να διασχίσει το δρόμο `(u, parent)`.
2020
long long subtree_loop_opt(long u, long parent) {
2121
long long sol = tip[u];
@@ -56,9 +56,10 @@ int main() {
5656
for (long i = 0; i < q; ++i) {
5757
long L, R;
5858
scanf("%li%li", &L, &R);
59+
L--, R--;
5960
assert(L == R);
6061

61-
printf("%lli\n", subtree_loop_opt(L-1, L-1));
62+
printf("%lli\n", subtree_loop_opt(L, L));
6263
}
6364

6465
return 0;

_includes/source_code/code/37-PDP/tiphunting/subtask3.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ vector<long long> subtree_loop_opt, supertree_root_opt;
1414

1515
long long positive_part(long long x) { return max(0LL, x); }
1616

17-
// Πρώτη διαπέραση η οποία υπολογίζει το `subtree_loop_opt` για την κορυφή `u`
17+
// Πρώτη διάσχιση η οποία υπολογίζει το `subtree_loop_opt` για την κορυφή `u`
1818
// κι όλους τους απογόνους της.
1919
//
2020
// subtree_loop_opt[u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
2121
// και καταλήγει πάλι πίσω στο `u`, παραμένοντας στο υποδέντρο που ορίζει
22-
// η κορυφή `u` -- με άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
22+
// η κορυφή `u`. Με άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
2323
// τον δρόμο `(u, parent)`.
2424
void compute_subtree_loop_opt(long u, long parent) {
2525
subtree_loop_opt[u] = tip[u];
@@ -31,9 +31,9 @@ void compute_subtree_loop_opt(long u, long parent) {
3131
}
3232
}
3333

34-
// Δεύτερη διαπέραση η οποία υπολογίζει το `supertree_root_opt` για την κορυφή
34+
// Δεύτερη διάσχιση η οποία υπολογίζει το `supertree_root_opt` για την κορυφή
3535
// `u` κι όλους τους απογόνους της, χρησιμοποιώντας τις τιμές
36-
// `subtree_loop_opt` που υπολογίσαμε ήδη στην πρώτη διαπέραση.
36+
// `subtree_loop_opt` που υπολογίσαμε ήδη στην πρώτη διάσχιση.
3737
//
3838
// supertree_root_opt[u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
3939
// από την κορυφή `u`, καταλήγει στη ρίζα τους δέντρου και
@@ -44,7 +44,9 @@ void compute_supertree_root_opt(long u, long parent, long w) {
4444

4545
// Αν η κορυφή `u` ΔΕΝ είναι ρίζα.
4646
if (parent != u)
47-
supertree_root_opt[u] = subtree_loop_opt[parent] + supertree_root_opt[parent] - positive_part(subtree_loop_opt[u] - 2*w) - w;
47+
supertree_root_opt[u] =
48+
subtree_loop_opt[parent] + supertree_root_opt[parent]
49+
- positive_part(subtree_loop_opt[u] - 2*w) - w;
4850

4951
for (auto [v, w]: tree[u])
5052
if (v != parent)
@@ -81,9 +83,7 @@ int main() {
8183
for (long i = 0; i < q; ++i) {
8284
long L, R;
8385
scanf("%li%li", &L, &R);
84-
L -= 1;
85-
R -= 1;
86-
86+
L--, R--;
8787
compute_subtree_loop_opt(R, R);
8888
compute_supertree_root_opt(R, R, 0);
8989

_includes/source_code/code/37-PDP/tiphunting/subtask4.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ vector<long long> subtree_loop_opt, supertree_loop_opt;
1414

1515
long long positive_part(long long x) { return max(0LL, x); }
1616

17-
// Πρώτη διαπέραση η οποία υπολογίζει το `subtree_loop_opt` για την κορυφή `u`
17+
// Πρώτη διάσχιση η οποία υπολογίζει το `subtree_loop_opt` για την κορυφή `u`
1818
// κι όλους τους απογόνους της.
1919
//
2020
// subtree_loop_opt[u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
2121
// και καταλήγει πάλι πίσω στο `u`, παραμένοντας στο υποδέντρο που ορίζει
22-
// η κορυφή `u` -- με άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
22+
// η κορυφή `u`. Με άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
2323
// τον δρόμο `(u, parent)`.
2424
void compute_subtree_loop_opt(long u, long parent) {
2525
subtree_loop_opt[u] = tip[u];
@@ -31,9 +31,9 @@ void compute_subtree_loop_opt(long u, long parent) {
3131
}
3232
}
3333

34-
// Δεύτερη διαπέραση η οποία υπολογίζει το `supertree_loop_opt` για την κορυφή
34+
// Δεύτερη διάσχιση η οποία υπολογίζει το `supertree_loop_opt` για την κορυφή
3535
// `u` κι όλους τους απογόνους της, χρησιμοποιώντας τις τιμές
36-
// `subtree_loop_opt` που υπολογίσαμε ήδη στην πρώτη διαπέραση.
36+
// `subtree_loop_opt` που υπολογίσαμε ήδη στην πρώτη διάσχιση.
3737
//
3838
// supertree_loop_opt[u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει αλλά
3939
// ΚΑΙ καταλήγει στην κορυφή `u`, και μένει πάντα ΕΚΤΟΣ του υποδέντρου που
@@ -43,7 +43,9 @@ void compute_supertree_loop_opt(long u, long parent, long w) {
4343

4444
// Αν η κορυφή `u` ΔΕΝ είναι ρίζα.
4545
if (parent != u)
46-
supertree_loop_opt[u] = positive_part(subtree_loop_opt[parent] + supertree_loop_opt[parent] - positive_part(subtree_loop_opt[u] - 2*w) - 2*w);
46+
supertree_loop_opt[u] =
47+
positive_part(subtree_loop_opt[parent] + supertree_loop_opt[parent]
48+
- positive_part(subtree_loop_opt[u] - 2*w) - 2*w);
4749

4850
for (auto [v, w]: tree[u])
4951
if (v != parent)
@@ -83,9 +85,10 @@ int main() {
8385
for (long i = 0; i < q; ++i) {
8486
long L, R;
8587
scanf("%li%li", &L, &R);
88+
L--, R--;
8689
assert(L == R);
8790

88-
printf("%lli\n", subtree_loop_opt[L-1] + supertree_loop_opt[L-1]);
91+
printf("%lli\n", subtree_loop_opt[L] + supertree_loop_opt[L]);
8992
}
9093

9194
return 0;

_includes/source_code/code/37-PDP/tiphunting/subtask5.cc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ vector<long long> subtree_loop_opt, supertree_root_opt;
1414

1515
long long positive_part(long long x) { return max(0LL, x); }
1616

17-
// Πρώτη διαπέραση η οποία υπολογίζει το `subtree_loop_opt` για την κορυφή `u`
17+
// Πρώτη διάσχιση η οποία υπολογίζει το `subtree_loop_opt` για την κορυφή `u`
1818
// κι όλους τους απογόνους της.
1919
//
2020
// subtree_loop_opt[u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
2121
// και καταλήγει πάλι πίσω στο `u`, παραμένοντας στο υποδέντρο που ορίζει
22-
// η κορυφή `u` -- με άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
22+
// η κορυφή `u`. Με άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
2323
// τον δρόμο `(u, parent)`.
2424
void compute_subtree_loop_opt(long u, long parent) {
2525
subtree_loop_opt[u] = tip[u];
@@ -31,9 +31,9 @@ void compute_subtree_loop_opt(long u, long parent) {
3131
}
3232
}
3333

34-
// Δεύτερη διαπέραση η οποία υπολογίζει το `supertree_root_opt` για την κορυφή
34+
// Δεύτερη διάσχιση η οποία υπολογίζει το `supertree_root_opt` για την κορυφή
3535
// `u` κι όλους τους απογόνους της, χρησιμοποιώντας τις τιμές
36-
// `subtree_loop_opt` που υπολογίσαμε ήδη στην πρώτη διαπέραση.
36+
// `subtree_loop_opt` που υπολογίσαμε ήδη στην πρώτη διάσχιση.
3737
//
3838
// supertree_root_opt[u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
3939
// από την κορυφή `u`, καταλήγει στη ρίζα τους δέντρου και
@@ -44,7 +44,9 @@ void compute_supertree_root_opt(long u, long parent, long w) {
4444

4545
// Αν η κορυφή `u` ΔΕΝ είναι ρίζα.
4646
if (parent != u)
47-
supertree_root_opt[u] = subtree_loop_opt[parent] + supertree_root_opt[parent] - positive_part(subtree_loop_opt[u] - 2*w) - w;
47+
supertree_root_opt[u] =
48+
subtree_loop_opt[parent] + supertree_root_opt[parent]
49+
- positive_part(subtree_loop_opt[u] - 2*w) - w;
4850

4951
for (auto [v, w]: tree[u])
5052
if (v != parent)
@@ -77,8 +79,7 @@ int main() {
7779

7880
long L, R;
7981
scanf("%li%li", &L, &R);
80-
L -= 1;
81-
R -= 1;
82+
L--, R--;
8283

8384
subtree_loop_opt.resize(n);
8485
compute_subtree_loop_opt(L, L);;
@@ -94,7 +95,8 @@ int main() {
9495
long new_L;
9596
scanf("%li%li", &new_L, &R);
9697
assert(L == new_L - 1);
97-
R -= 1;
98+
R--;
99+
98100
printf("%lli\n", subtree_loop_opt[R] + supertree_root_opt[R]);
99101
}
100102

0 commit comments

Comments
 (0)