1
+ // Solution Provided by Jesse Sparks
2
+ // See GitHub: https://github.com/jsparks125
3
+
4
+ #include < chrono>
5
+ #include < cmath>
6
+ #include < cstdio>
7
+ #include < map>
8
+ #include < queue>
9
+ #include < set>
10
+ #include < stack>
11
+ #include < tuple>
12
+ #include < vector>
13
+ #include < iostream>
14
+ #include < fstream>
15
+ #include < algorithm>
16
+ #include < unordered_map>
17
+ #include < string>
18
+
19
+ int max_depth = 0 ;
20
+
21
+ struct node
22
+ {
23
+ int value;
24
+ int depth;
25
+ node* parent;
26
+
27
+ node (int v, int d, node* p)
28
+ {
29
+ value = v;
30
+ depth = d;
31
+ parent = p;
32
+ }
33
+
34
+ node ()
35
+ {
36
+ value = -1 ;
37
+ depth = -1 ;
38
+ }
39
+ };
40
+
41
+ struct subtree
42
+ {
43
+ int root_node;
44
+ int depth;
45
+ int next_calc_depth = -1 ;
46
+ unsigned long long next_calc = 0 ;
47
+ unsigned long long next_sum = 0 ;
48
+
49
+ subtree ()
50
+ {}
51
+
52
+ subtree (int d)
53
+ {
54
+ depth = d;
55
+ }
56
+
57
+ subtree (int cn, int d)
58
+ {
59
+ root_node = cn;
60
+ depth = d;
61
+ next_calc_depth = d;
62
+ }
63
+ };
64
+
65
+ std::unordered_map<int , node> nodes;
66
+
67
+ int main ()
68
+ {
69
+ int num_nodes, num_sets;
70
+ std::cin >> num_nodes >> num_sets;
71
+ int child_node, parent_node;
72
+
73
+ std::vector<std::pair<int , int >> node_list;
74
+ for (int i = 1 ; i < num_nodes; i++)
75
+ {
76
+ std::cin >> child_node >> parent_node;
77
+ if (parent_node > child_node)
78
+ node_list.push_back (std::pair<int , int >(child_node, parent_node));
79
+ else
80
+ node_list.push_back (std::pair<int , int >(parent_node, child_node));
81
+ }
82
+
83
+ std::pair<int , int > first_node_pair = *(node_list.begin ());
84
+ parent_node = first_node_pair.first ;
85
+ child_node = first_node_pair.second ;
86
+ nodes[parent_node] = node (parent_node, 0 , nullptr );
87
+ nodes[child_node] = node (child_node, 1 , &nodes[parent_node]);
88
+
89
+ for (auto it = std::next (node_list.begin ()); it != node_list.end (); ++it)
90
+ {
91
+ parent_node = it->first ;
92
+ child_node = it->second ;
93
+ node* parent = &nodes[parent_node];
94
+ int parent_depth = parent->depth ;
95
+ int current_depth = parent_depth + 1 ;
96
+
97
+ if (current_depth > max_depth)
98
+ max_depth = current_depth;
99
+
100
+ nodes[child_node] = node (child_node, current_depth, parent);
101
+ }
102
+
103
+ for (int i = 0 ; i < num_sets; i++)
104
+ {
105
+ int n;
106
+ std::cin >> n;
107
+
108
+ if (n > 1 )
109
+ {
110
+ int loadTime = 0 ;
111
+
112
+ std::map<int , subtree> subtrees;
113
+ std::map<int , std::map<int , node>> nodes_by_depth;
114
+
115
+ unsigned long long int new_kitty_sum = 0 ;
116
+ int subtree_max_depth = 0 ;
117
+
118
+ // Load nodes from the current set and store them by their depth
119
+ for (int j = 0 ; j < n; j++)
120
+ {
121
+ int current_node_key;
122
+ std::cin >> current_node_key;
123
+ node current_node = nodes[current_node_key];
124
+
125
+ int current_depth = current_node.depth ;
126
+ if (current_depth > subtree_max_depth)
127
+ subtree_max_depth = current_depth;
128
+
129
+ nodes_by_depth[current_depth][current_node.value ] = current_node;
130
+ }
131
+
132
+ // Start at the bottom of the tree and work upward, combining nodes as they hit their common ancestor
133
+ for (int j = subtree_max_depth; j > 0 ; j--)
134
+ {
135
+ auto process_roots = nodes_by_depth.find (j);
136
+
137
+ // We can easily shift a node up as long as it is the only node at its current level and there are no nodes directly above it
138
+ // This alleviates quite a bit of processing on very deep trees
139
+ if (process_roots->second .size () == 1 )
140
+ {
141
+ auto next_roots_iter = nodes_by_depth.find (j - 1 );
142
+ if (next_roots_iter == nodes_by_depth.end ())
143
+ {
144
+ int shifted = 0 ;
145
+ node current_node = process_roots->second .begin ()->second ;
146
+ int previous_node_value = current_node.value ;
147
+ while (next_roots_iter == nodes_by_depth.end () && (j - shifted) > 0 )
148
+ {
149
+ shifted++;
150
+ next_roots_iter = nodes_by_depth.find (j - shifted);
151
+ if (next_roots_iter == nodes_by_depth.end ())
152
+ {
153
+ previous_node_value = current_node.parent ->value ;
154
+ current_node.parent = current_node.parent ->parent ;
155
+ }
156
+ }
157
+ nodes_by_depth[j - (shifted - 1 )].insert (std::pair<int , node>(previous_node_value, current_node));
158
+ process_roots = nodes_by_depth.find (j - (shifted - 1 ));
159
+ j -= (shifted - 1 );
160
+ }
161
+ }
162
+
163
+ // Check all of the roots at the current level to see if they have a common ancestor or if their parent exists at the next level
164
+ // If so, they can be combined
165
+ for (auto root_iter = process_roots->second .begin (); root_iter != process_roots->second .end (); ++root_iter)
166
+ {
167
+ node current_node = root_iter->second ;
168
+ if (current_node.parent == nullptr )
169
+ break ;
170
+ node* parent_node = current_node.parent ;
171
+
172
+ auto parent_iter = nodes_by_depth[j - 1 ].find (current_node.parent ->value );
173
+ if (parent_iter != nodes_by_depth[j - 1 ].end ())
174
+ {
175
+ subtree* next_root_subtree;
176
+ auto next_iter = subtrees.find (parent_iter->second .value );
177
+ if (next_iter != subtrees.end ())
178
+ next_root_subtree = &next_iter->second ;
179
+ else
180
+ {
181
+ auto nrs_iter = subtrees.insert (std::pair<int , subtree>(parent_iter->first , subtree (parent_iter->first , j - 1 ))).first ;
182
+ next_root_subtree = &(nrs_iter->second );
183
+ next_root_subtree->next_calc = (uint64_t (parent_iter->second .depth - (j - 1 )) * uint64_t (parent_iter->second .value )) % 1000000007 ;
184
+ next_root_subtree->next_sum = parent_iter->second .value ;
185
+ nodes_by_depth[j - 1 ][parent_iter->first ].value = parent_iter->first ;
186
+ }
187
+
188
+ unsigned long long next_calc = next_root_subtree->next_calc + (next_root_subtree->next_sum * (next_root_subtree->next_calc_depth - (j - 1 ))) % 1000000007 ;
189
+ unsigned long long next_child_sum = next_root_subtree->next_sum ;
190
+ next_root_subtree->next_calc = next_calc;
191
+ next_root_subtree->next_calc_depth = j - 1 ;
192
+
193
+ auto current_iter = subtrees.find (current_node.value );
194
+ if (current_iter != subtrees.end ())
195
+ {
196
+ subtree* current_subtree = ¤t_iter->second ;
197
+ int current_index = current_subtree->next_calc_depth - (j - 1 );
198
+ unsigned long long new_sum = next_calc * (current_subtree->next_sum );
199
+ unsigned long long current_product = current_subtree->next_calc + (current_subtree->next_sum * uint64_t (current_index)) % 1000000007 ;
200
+ unsigned long long second_sum = next_child_sum * (current_product % 1000000007 );
201
+ new_kitty_sum += (new_sum % 1000000007 ) + (second_sum % 1000000007 );
202
+ next_root_subtree->next_calc += (current_product % 1000000007 );
203
+ next_root_subtree->next_calc %= 1000000007 ;
204
+ next_root_subtree->next_sum += current_subtree->next_sum ;
205
+ }
206
+ else
207
+ {
208
+ int current_depth = current_node.depth ;
209
+ int current_index = current_depth - (j - 1 );
210
+ int current_sum = current_node.value ;
211
+ unsigned long long new_sum = next_calc * uint64_t (current_sum);
212
+ unsigned long long current_product = uint64_t (current_sum) * uint64_t (current_index);
213
+ unsigned long long second_sum = next_child_sum * (current_product % 1000000007 );
214
+ new_kitty_sum += (new_sum % 1000000007 ) + (second_sum % 1000000007 );
215
+ int new_index = current_depth - next_root_subtree->depth ;
216
+ next_root_subtree->next_calc += (current_product % 1000000007 );
217
+ next_root_subtree->next_calc %= 1000000007 ;
218
+ next_root_subtree->next_sum += uint64_t (current_sum);
219
+ }
220
+ }
221
+ else
222
+ {
223
+ int new_root_depth = j - 1 ;
224
+ current_node.parent = parent_node->parent ;
225
+ nodes_by_depth[new_root_depth][parent_node->value ] = current_node;
226
+ }
227
+ }
228
+ }
229
+
230
+ std::cout << new_kitty_sum % 1000000007 << std::endl;
231
+ }
232
+ else
233
+ {
234
+ std::cin >> n;
235
+ std::cout << 0 << std::endl;
236
+ }
237
+ }
238
+
239
+ return 0 ;
240
+ }
0 commit comments