@@ -18,6 +18,27 @@ vector<long long> subtree_loop_opt, supertree_loop_opt, supertree_root_opt;
1818
1919long 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);
0 commit comments