December 3, 2021
Cells in an -by- grid are colored in monochrome:
Find the smallest non-negative integer , such that there exists no square of cells in , with side length , whose perimeter consists entirely of black cells.
Codeforces/Polygon practice problem.
The problem reduces to finding the side length of the largest square whose perimeter is entirely black, or if no black cells exist. We denote such squares valid. Let store the largest length of consecutive black cells, starting from cell and moving left. For white cell , let . Similarly, define for moving upwards. The indices for may be computed in each with the recurrence
and similarly for .
Each square in may be specified by a tuple of upper-left corner and side length . The square is valid if and only if all four edges are entirely black; that is, all four conditions below are satisfied:
For each of the squares, this check for validity costs .
First, compute , similarly to , but for lengths of black cells moving right, and downwards, respectively.
Each of the upper-left-to-bottom-right diagonals may be specified by as the diagonal which passes through cell . Denote the diagonals by . Note that specifies the same diagonal as .
For a given upper-left corner , we check all squares for validity by querying a DSU for the maximum valid for that . To begin, define the reach over the diagonal:
and reverse reach :
Intuitively, the reach specifies the maximum side length for a valid square with bottom-right corner , while the reverse reach specifies similarly for the upper-left corner . In other words, square is valid if and only if both conditions below are satisfied:
We can remove condition ’s dependence on by defining the discounted reach :
may now be rewritten:
We process the upper-left corners along diagonal in increasing order of , decreases. Thus, the set of indices which satisfy never shrinks. More specifically, at , all bottom-right corners with must be added to . As we have already processed at this point, only the bottom-right corners which satisfy need to be added. We may query for these in by pre-sorting in , with radix sort, all the on the diagonal.
At a given upper-left corner , then, the maximal valid bottom-right corner is the maximal which also satisfies :
Formally, we wish to make two types of queries to set :
Observe that for some , if , then . This leads us to consider implementing with a DSU. Should we process upper-left corners in decreasing order of instead of increasing order, increases, and ).
Intuitively, the reach specifies the maximum side length for a valid square with bottom-right corner , while the reverse reach specifies similarly for the upper-left corner . In other words, square is valid if and only if both conditions below are satisfied:
We can remove condition ’s dependence on by defining the discounted reach :
may now be rewritten:
We process the upper-left corners along diagonal in increasing order of , decreases. Thus, the set of indices which satisfy never shrinks. More specifically, at , all bottom-right corners with must be added to . As we have already processed at this point, only the bottom-right corners which satisfy need to be added. We may query for these in by pre-sorting in , with radix sort, all the on the diagonal.
At a given upper-left corner , then, the maximal valid bottom-right corner is the maximal which also satisfies :
Formally, we wish to make two types of queries to set :
Observe that for some , if , then . This leads us to consider implementing with a DSU. Should we process upper-left corners in decreasing order of instead of increasing order, increases, and never grows. Thus, instead of , we wish to support .
Before moving on to the reduction to DSU, we first discuss an example.
Take, for example, the following input with from the square with upper-left corner at :
110111 011110 010011 111011 111111 111111
Consider the processing of the major diagonal . As mentioned, we step through the diagonal in decreasing order of .
Observe, as noted previously, that intuitively calculates the maximum row index which may serve as a bottom-right corner for a given upper-left corner . In addition, for any upper-left corner , it may form a valid square with bottom-right corner as long as and . These together describe conditions and , respectively.
To visualize the operations on , we arrange it onto a line with corner on the left and on the right. Initially, all corners are part of :
|||||| 012345
At any point in time, we either remove an element from , or we stand at some point on the line, and look left to identify the index of the first
|
blocking our view. Since is unchanged prior to visiting , we take that as our first example. As is , we must remove all from where is smaller than . Thus, we remove from :|||_|| 012345
Intuitively, has been removed from consideration as a bottom-right corner. This is because any bottom or right edges which extend from it can no longer reach any upper-left corners we have yet to process, or the upper-left corner we are currently processing: .
We wrap up processing upper-left corner by querying for the maximal bottom-right corner with , which is the bottom-right corner . To visualize this, imagine standing at index on the line and looking left for the first
|
blocking your vision (index counts). This is the