Editorial for Wesley's Anger Contest 1 Problem 7 - Arithmetic Subtrees
Submitting an official solution before solving the problem yourself is a bannable offence.
For the first subtask, we can depth first search / breadth first search for each of the updates and queries and update/query the values in the depth range.
For the second subtask, we can treat the graph as an array and use two segment trees that supports range increments and sum queries with lazy propagation. Let be the value of each vertex. The first segment tree will support range updates and queries for , while the second segment tree will support range updates and queries for . To update an interval, we will update the first segment tree with the value . However, we have added , when we really want . To correct this, we can see that the term is constant, so we can update the second segment tree with this value.
For the third subtask, the question is asking us to perform operation in the subtree of . We can flatten the tree with an Euler tour, and reindexing vertices based on their preorder traversal index. For each subgraph, we will maintain two segment trees that supporting range increment and sum queries with lazy propagation. The first segment tree will support range updates and queries for , where is the depth of vertex , while the second segment tree will support range updates and queries for . To update or query the subtree of , we will look at the range , where is the preorder index of and is the maximum preorder index in the subtree of . For updates, we can use a method similar to subtask 2.
For the fourth subtask, we can tree the graph as an array, indexed based on the order of vertices sorted in non decreasing order of depth, and use a segment tree that supports range updates and queries for , where is the value of the vertex, is the minimum index with depth , and is the maximum index with depth .
For the fifth subtask, we will divide the tree into "fragments". A fragment is a set of vertices such that the edges between each vertex in the fragment and its parent form a connected subgraph.
One way to do this is to iterate through the vertices in non increasing order of depth. For each vertex, we will go through its adjacency list and add the size of each child to a sum. If this sum goes over (which will be determined later), we will create a fragment containing all vertices in the subtrees of the children in the adjacency list up to and including the current child. Decrement the size, and continue going through the remaining children in a similar manner. There is also a way to build this using depth first search.
There will be around fragments in total. For a subtree of a vertex, it can be shown that there is at most one subgraph that is has some vertices inside the subtree, and some vertices outside the subtree. All other fragments will either have all of its vertices inside the subtree, or all of its vertices outside the subtree.
For each subgraph, we will maintain two segment trees that supporting range increment and sum queries with lazy propagation. These segment tree will be indexed based on the order of vertices in the subgraph sorted in non decreasing order of depth, similar to subtask 4. Let be the value of vertex . The first segment tree will support range updates and queries for , where is the depth of vertex , while the second segment tree will support range updates and queries for .
To handle updates, first we will go through all the vertices in the subgraph of , and update the value in the segment tree for vertices that are in the subtree of with depths between and . Checking if a vertex is in the subtree of can be done similar to subtask 3, by flattening the tree with an Euler tour. Since there are vertices in the subgraph with segment tree updates taking time, this will take time in total. One optimization is to propagate all the values in the segment tree to the leaves, collect the values at the leaves into a single array, and update the array instead of the segment tree. We can then rebuild the segment tree after all the updates in the subgraph, which will take time in total. Afterwards, we can go through all the fragment and update the segment trees of the fragments in the subtree of . Note that it may be the case that only part (or none) of the range of the depths for that subgraph intersects the range . Updating the segment tree can be done similarly to subtask 2. This will take time in total.
Queries can be handled in a similar fashion, by first checking the vertices of the subgraph that is partially in the subtree of , before querying the fragments that are fully in the subtree of . The time complexity is the same as updates.
Here, it is optimal to choose .