Editorial for WC '15 Finals S5 - Supply Chain
Submitting an official solution before solving the problem yourself is a bannable offence.
One major step in solving this problem is the reduction to solving it for a line of pastures (starting with pasture ) rather than a cycle, which is much more manageable. Let's consider having two lines of pastures each. The first line will consist of pastures (made by removing bridge ), while the second will consist of pastures (made by removing bridge ). If we compute the number of bananas delivered in each line and add these two values together, it may exceed the number of bananas delivered in the original cycle – but by how much? The only bananas which will be counted twice will be all of those delivered by trucks which are light enough to drive around the entire cycle in either direction – namely, the trucks whose weights are no larger than the minimum weight supported by any bridge . Therefore, if we can maintain this minimum value (which is easy) and be able to query the sum of the values of trucks whose values are no larger than it (which will be doable), we can go ahead and solve the problem for both of these lines independently, and then combine their answers!
Now that we're dealing with a line (let's say the first line, consisting of pastures to in order), let be the maximum truck weight that would be capable of reaching each pasture . We have , while for . Note that is a non-increasing sequence. The number of bananas delivered to pasture is then the sum of the values of trucks whose values are no larger than . Handling each day independently, we can compute the array in time, and then compute the total number of bananas delivered on it efficiently in various ways. For example, we can consider each truck in turn, use binary search to find the last pasture that truck can reach (i.e., the largest such that ), and add to our result. After computing the results for both lines, we must remember to subtract the double-counted bananas, which can be done by summing the bananas delivered by light-enough trucks in time. This yields a solution with a running time of . Similar and solutions are possible.
In order to optimize this approach, we'll need to be able to update the answer from day to day without re-computing it from scratch, which will require a couple of data structures to maintain and update useful information about the trucks and pastures.
Firstly, for the trucks, it seems useful to be able to query the sum of the values of trucks whose values are no larger than some given value (for example, this is exactly what's required to compute the number of double-counted bananas each day). Fortunately, there exists a simple data structure which does exactly that – a binary indexed tree (also known as a Fenwick tree). We'll initialize the tree with each truck by adding to index , and each time a truck 's weight changes from to , we'll subtract from index and add to index . We'll be querying this tree for the sum of the values of trucks whose values are no larger than some weight – let's call this sum . Each update and query on this tree will take time, where is the maximum possible truck weight ().
Secondly, for the pastures in a line, we'll want a data structure to represent their corresponding array. Let's consider only the set of "interesting" indices at which changes (decreases), plus a sentinel value of . We then have an increasing list such that each interval of indices has a uniform value, which means that each pasture in that interval will receive the same number of bananas (namely, of them). To allow this list to be updated as necessary, we'll want to store it as a set (a balanced binary search tree) of pairs , rather than maintaining the actual arrays and . This set is initialized in by iterating over the pastures in order and inserting each one which is preceded by a bridge with a new minimum weight limit. Each time a bridge 's weight limit is reduced to , this set can be updated in amortized by potentially adding a point , and deleting existing points where and .
Now that both of these data structures are in place, let's consider how to use them to update each line's answer after each event. When a truck 's weight changes from to , we should determine how many pastures are reachable by trucks with weight and how many pastures are reachable by trucks with weight , and increase the answer by . Each of these values can be looked up in our set in time using binary search, or even in time if we maintain an accompanying set of points searchable by value (in other words a set of pairs in addition to the set of pairs ). When a bridge's supported weight decreases and we insert and/or delete points from our set, some intervals of pastures with equal values (that is, the intervals between adjacent indices in the set) will change, and we can update the answer accordingly. For example, if an interval of pastures all have their values reduced from to , we should decrease the answer by . An amortized constant number of pasture intervals will change as a result of each such event, meaning that it can be handled in amortized time. The total time complexity of this algorithm is , where is again the maximum possible truck weight.
Comments