@@ -14,7 +14,7 @@ using vvl = vector<vector<long>>;
1414vvll tree;
1515vl tip, depth, parent, parent_weight;
1616vvl pred;
17- vector<long long > subtree_loop_opt, supertree_loop_opt, supertree_root_opt ;
17+ vector<long long > best_subtree_tour, best_supertree_tour, best_supertree_root_walk ;
1818
1919long long positive_part (long long x) { return max (0LL , x); }
2020
@@ -34,21 +34,20 @@ void init(int n) {
3434 parent_weight.resize (n, 0 );
3535
3636 pred.resize (kMaxH , vector<long >(n));
37- subtree_loop_opt .resize (n);
38- supertree_loop_opt .resize (n);
39- supertree_root_opt .resize (n);
37+ best_subtree_tour .resize (n);
38+ best_supertree_tour .resize (n);
39+ best_supertree_root_walk .resize (n);
4040}
4141
4242// Διασχίζει το δέντρο `tree` ξεκινώντας από την κορυφή `u` και υπολογίζει
4343// αναδρομικά τις τιμές `depth[v]`, `parent[v]` και `parent_weight[v]` για κάθε
4444// κορυφή `v != u` στο υποδέντρο της `u`. Οι τιμές `depth[u]`, `parent[u]` και
4545// `parent_weight[u]` θα πρέπει να έχουν ήδη υπολογισθεί από τον caller.
4646//
47- // `depth[u]`: Το βάθος του `u` στο δέντρο, το οποίο ορίζεται ως το πλήθος
48- // των ακμών στο μονοπάτι από τον `u` προς τη ρίζα. Για παράδειγμα το βάθος
49- // της ρίζας είναι 0.
50- // `parent[u]`: Ο γονέας του `u`.
51- // `parent_weight[u]`: Κόστος του δρόμου που συνδέει τον `u` με τον γονέα του.
47+ // `depth[u]`: Το βάθος του `u` στο δέντρο, το οποίο ορίζεται ως το πλήθος των
48+ // ακμών στο μονοπάτι από τον `u` προς τη ρίζα. Για παράδειγμα το βάθος της
49+ // ρίζας είναι 0. `parent[u]`: Ο γονέας του `u`. `parent_weight[u]`: Κόστος
50+ // του δρόμου που συνδέει τον `u` με τον γονέα του.
5251void compute_auxiliary (int u) {
5352 for (auto [v, w]: tree[u]) {
5453 if (v == parent[u]) continue ;
@@ -61,65 +60,65 @@ void compute_auxiliary(int u) {
6160}
6261
6362// Διασχίζει το δέντρο `tree` και υπολογίζει αναδρομικά τις τιμές
64- // `subtree_loop_opt ` για την κορυφή `u` κι όλους τους απογόνους της.
63+ // `best_subtree_tour ` για την κορυφή `u` κι όλους τους απογόνους της.
6564//
66- // `subtree_loop_opt [u]`: Το κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
67- // και καταλήγει πάλι πίσω στο `u`, παραμένοντας στο υποδέντρο που ορίζει
68- // η κορυφή `u`. Mε άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει
69- // τον δρόμο `(u, parent)`.
70- void compute_subtree_loop_opt (long u) {
71- subtree_loop_opt [u] = tip[u];
65+ // `best_subtree_tour [u]`: Το κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
66+ // και καταλήγει πάλι πίσω στο `u`, παραμένοντας στο υποδέντρο που ορίζει η
67+ // κορυφή `u`. Mε άλλα λόγια, η διαδρομή απαγορεύεται να διασχίσει τον δρόμο
68+ // `(u, parent)`.
69+ void compute_best_subtree_tour (long u) {
70+ best_subtree_tour [u] = tip[u];
7271
7372 for (auto [v, w]: tree[u]) {
7473 if (v == parent[u]) continue ;
75- compute_subtree_loop_opt (v);
76- subtree_loop_opt [u] += positive_part (subtree_loop_opt [v] - 2 *w);
74+ compute_best_subtree_tour (v);
75+ best_subtree_tour [u] += positive_part (best_subtree_tour [v] - 2 *w);
7776 }
7877}
7978
8079// Διασχίζει το δέντρο `tree` και υπολογίζει αναδρομικά τις τιμές
8180// `subtree_root_opt` για την κορυφή `u` κι όλους τους απογόνους της,
82- // χρησιμοποιώντας τις τιμές `subtree_loop_opt ` που υπολογίσαμε ήδη στην
81+ // χρησιμοποιώντας τις τιμές `best_subtree_tour ` που υπολογίσαμε ήδη στην
8382// προηγούμενη διάσχιση.
8483//
85- // `supertree_root_opt [u]`: Το κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει
86- // από την κορυφή `u`, καταλήγει στη ρίζα του δέντρου και
87- // μένει πάντα ΕΚΤΟΣ του υποδέντρου που ορίζει η `u`. Το φιλοδώρημα της κορυφής
88- // `u` ΔΕΝ προσμετράται.
89- void compute_supertree_root_opt (long u) {
90- supertree_root_opt [u] = 0 ;
84+ // `best_supertree_root_walk [u]`: Το κέρδος της βέλτιστης διαδρομής η οποία
85+ // ξεκινάει από την κορυφή `u`, καταλήγει στη ρίζα του δέντρου και μένει πάντα
86+ // ΕΚΤΟΣ του υποδέντρου που ορίζει η `u`. Το φιλοδώρημα της κορυφής `u` ΔΕΝ
87+ // προσμετράται.
88+ void compute_best_supertree_root_walk (long u) {
89+ best_supertree_root_walk [u] = 0 ;
9190
9291 // Αν η κορυφή `u` ΔΕΝ είναι ρίζα.
9392 if (parent[u] != u)
94- supertree_root_opt [u] =
95- subtree_loop_opt [parent[u]] + supertree_root_opt [parent[u]]
96- - positive_part (subtree_loop_opt [u] - 2 *parent_weight[u]) - parent_weight[u];
93+ best_supertree_root_walk [u] =
94+ best_subtree_tour [parent[u]] + best_supertree_root_walk [parent[u]]
95+ - positive_part (best_subtree_tour [u] - 2 *parent_weight[u]) - parent_weight[u];
9796
9897 for (auto [v, w]: tree[u])
9998 if (v != parent[u])
100- compute_supertree_root_opt (v);
99+ compute_best_supertree_root_walk (v);
101100}
102101
103102// Διασχίζει το δέντρο `tree` και υπολογίζει αναδρομικά τις τιμές
104- // `subtree_loop_opt ` για την κορυφή `u` κι όλους τους απογόνους της,
105- // χρησιμοποιώντας τις τιμές `subtree_loop_opt ` που υπολογίσαμε ήδη στην
103+ // `best_subtree_tour ` για την κορυφή `u` κι όλους τους απογόνους της,
104+ // χρησιμοποιώντας τις τιμές `best_subtree_tour ` που υπολογίσαμε ήδη στην
106105// προηγούμενη διάσχιση.
107106//
108- // supertree_loop_opt [u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει αλλά
107+ // best_supertree_tour [u] = κέρδος της βέλτιστης διαδρομής η οποία ξεκινάει αλλά
109108// ΚΑΙ καταλήγει στην κορυφή `u`, και μένει πάντα ΕΚΤΟΣ του υποδέντρου που
110109// ορίζει η `u`. Το φιλοδώρημα της κορυφής `u` ΔΕΝ προσμετράται.
111- void compute_supertree_loop_opt (int u) {
112- supertree_loop_opt [u] = 0 ;
110+ void compute_best_supertree_tour (int u) {
111+ best_supertree_tour [u] = 0 ;
113112
114113 // Αν η κορυφή `u` ΔΕΝ είναι ρίζα.
115114 if (parent[u] != u)
116- supertree_loop_opt [u] =
117- positive_part (subtree_loop_opt [parent[u]] + supertree_loop_opt [parent[u]]
118- - positive_part (subtree_loop_opt [u] - 2 *parent_weight[u]) - 2 *parent_weight[u]);
115+ best_supertree_tour [u] =
116+ positive_part (best_subtree_tour [parent[u]] + best_supertree_tour [parent[u]]
117+ - positive_part (best_subtree_tour [u] - 2 *parent_weight[u]) - 2 *parent_weight[u]);
119118
120119 for (auto [v, w]: tree[u])
121120 if (v != parent[u])
122- compute_supertree_loop_opt (v);
121+ compute_best_supertree_tour (v);
123122}
124123
125124// Υπολογίζει τον πίνακα `pred` έτσι ώστε για κάθε 0 <= h <= H, 0 <= u < N:
@@ -209,17 +208,17 @@ int main() {
209208
210209 compute_pred ();
211210
212- compute_subtree_loop_opt (0 );
213- compute_supertree_loop_opt (0 );
214- compute_supertree_root_opt (0 );
211+ compute_best_subtree_tour (0 );
212+ compute_best_supertree_tour (0 );
213+ compute_best_supertree_root_walk (0 );
215214
216215 for (long i = 0 ; i < q; ++i) {
217216 long L, R;
218217 scanf (" %li%li" , &L, &R);
219218 L--, R--;
220219
221220 if (L == R) {
222- printf (" %lli\n " , subtree_loop_opt [L] + supertree_loop_opt [L]);
221+ printf (" %lli\n " , best_subtree_tour [L] + best_supertree_tour [L]);
223222 continue ;
224223 }
225224
@@ -230,23 +229,26 @@ int main() {
230229 if (u == -1 ) {
231230 // Η κορυφή `L` είναι πρόγονος της `R`.
232231 assert (z == L);
233- sol = supertree_root_opt[R] - supertree_root_opt[L] + supertree_loop_opt[L] + subtree_loop_opt[R];
232+ sol = best_supertree_root_walk[R] - best_supertree_root_walk[L]
233+ + best_supertree_tour[L] + best_subtree_tour[R];
234234 } else if (v == -1 ) {
235235 // Η κορυφή `R` είναι πρόγονος της `L`.
236236 assert (z == R);
237- sol = supertree_root_opt[L] - supertree_root_opt[R] + supertree_loop_opt[R] + subtree_loop_opt[L];
237+ sol = best_supertree_root_walk[L] - best_supertree_root_walk[R]
238+ + best_supertree_tour[R] + best_subtree_tour[L];
238239 } else {
239240 // Οι κορυφές `L, R` έχουν κοινό πρόγονο τον `z != L, R`.
240241 assert (pred[0 ][u] == z);
241242 assert (pred[0 ][v] == z);
242243
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)
244+ sol =
245+ best_supertree_root_walk[L] - best_supertree_root_walk[u] + best_subtree_tour[L] // (a)
246+ + best_supertree_root_walk[R] - best_supertree_root_walk[v] + best_subtree_tour[R] // (b)
247+ + best_subtree_tour[z] // (c1)
248+ - positive_part (best_subtree_tour[u] - 2 *parent_weight[u]) // (c2)
249+ - positive_part (best_subtree_tour[v] - 2 *parent_weight[v]) // (c3)
250+ + best_supertree_tour[z] // (d)
251+ - (parent_weight[u] + parent_weight[v]); // (e)
250252 }
251253
252254 printf (" %lli\n " , sol);
0 commit comments