ACM ICPC World Finals 2017

Problem D: Money for Nothing

Shortest judge solution: 1552 bytes. Shortest team solution (during contest): 1178 bytes.

Python solutions by the judges: only Pypy

First, observe that this is at heart a geometry problem. We are given a set of lower-left and upper-right vertices, and we’re asked for the area of the largest rectangle (with sides parallel to the axes) between some two chosen corners. One observation we make is that we can prune the input set. If there are two lower-left corners, (x1, y1) and (x2, y2), with x1 ≤ x2 and y1 ≤ y2, then we can remove (x2, y2) from the set. After this pruning, the set of lower-left corners forms a sequence L1, L2, L3, . . . , Ln, with Li = (xi, yi), and xi < xi+1, yi > yi+1. We can perform similar pruning on the upper-right corner set, getting the sequence U1, U2, . . . , Um, with Ui = (pi, qi), and again pi < pi+1 and qi > qi+1.

We’ll cover two solutions to the problem. The first one is less geometric. Define u(i) to be the index of the optimum upper-right corner for Li – that is, the rectangle Li, Uu(i) has area no smaller than any other Li, Uj. In the case of ties, choose the rightmost one. We’re claiming that u(i) is non-decreasing. A geometric proof is to draw out the picture, and notice that for any i < j, k < l, the sum of areas of Li Uk and Lj Ul is larger than the sum of areas Li Ul and Lj Uk. You can also just write out the areas and see the inequality holds.

This allows a divide-and-conquer solution. Take the middle of all the Lis, and find u(i) (through a linear scan). Then, for all j < i, we can consider only the upper right corners up to u(i), and for all the j > i we can consider only the upper corners starting from u(i), and recurse into both branches. Since we’re halving the set of Ls at each pass, we will have log n levels of branching, and in each of the levels each of the Us is getting considered only for one interval (with the exception of the boundaries, but these sum up to O(n log n) as well), so the runtime will be O((m + n) log n).

The other solution is geometric. For any two points Ui, Uj, let us consider the set of points L for which Ui gives a larger rectangle than Uj. The boundary of this set is a straight line, so the set of points L for which Ui is the best choice is an intersection of half-planes, i.e., a convex polygon which is possibly unbounded in some directions. The division of the plane into these polygons contains a total of O(n) vertices, and so we can run a sweep-line algorithm, with the events being a point from L appears, or the set of regions changes. This will run in O((m + n) log(m)) time.