Editorial for Back From Summer '17 P6: Crowded Cities
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Note that the order of length vs width does not matter since we can rotate the blocks by 90 degrees. We can prove that it is optimal to have the longer side always be either the length or width. We can then rotate to make sure the length is always the longer (or equal) side, and ignore the option to rotate later when we are trying to get the solution.
Subtask 1
Since , it is possible to go through permutations of blocks. For each permutation, greedily combine the front blocks 1 by 1 until you either reach the end of the sequence, or find a block that cannot stack on top of the previous block.
After you go through all the permutations, output the sequence with the greatest population.
Runtime complexity:
Subtask 2
Since all the block heights, lengths and widths are the same, you can simply sort by one of the dimensions and greedily combine all the blocks in greatest to least order.
Runtime complexity:
Subtask 3
Since , we can go through each pair of points and see which one can stack on top of each other. Once we create a directed acyclic graph (DAG), we can find the longest path using topological sort.
Runtime complexity:
Subtask 4
Since , we can always ignore the height factor, leaving us with only 2 dimensions. We can then sort to eliminate the length and do the classical Longest Increasing Subsequence problem to solve it.
Runtime complexity:
Subtask 5
After solving subtask 4, we realize that we can also sort by the height factor, and solve a 2D version of the Longest Increasing Subsequence problem. To do this, we can use a 2D segment tree, which will let us query the largest value with .
Runtime complexity:
Subtask 6
A 2D segment tree takes many times more integers to store the value than a standard 2D array. This will easily MLE as the grid is quite large. To get around this we can use a 2D Binary Index Tree, but instead of storing sums, we can use it to store the largest value and query from . It is also much simpler to code than a 2D segment tree.
This uses no more memory than a grid, which will allow it to pass.
Runtime complexity:
Comments
why is the longest increasing subsequence the one that holds the most people?
How to construct the LIS after getting most PPL?
I had a similar idea during the contest, but I can't see how to deal with the case of equal heights after sorting by height. Can somebody explain this?
Tie break on max(length, width), then on min(length, width).
This is the intended solution. This can be made simpler if you simply swap the length and width to make sure the longer side is always the length or always the width, then sort by that.
Thanks, that was a silly mistake by me!