Source: USAMO-2020-P2
Category: Extremal Problems

Problem: Consider a hollow cube of dimensions $2020\\times2020\\times2020$ whose six faces are each divided into $2020\\times2020$ unit squares. A solid rectangular block of dimensions $1\\times1\\times2020$ is called a \"brick.\" Place several such bricks inside the cube such that: (1) The two $1\\times1$ faces of each brick coincide with two unit squares on a pair of opposite faces of the cube (there are $3\\times2020^2$ ways to place a brick); (2) Any two bricks have no interior points in common; (3) Each of the four $1\\times2020$ faces of every brick either shares interior points with a face of the cube or shares interior points with a $1\\times2020$ face of another brick. Find the minimum possible number of bricks placed. Note: The interior points of a brick refer to points not on its faces or edges; the interior points of a face refer to points not on the boundary of the face.

Answer: 3030

Reference solution:
Let the cube be represented by the region $[0, 2020]^3$ in a Cartesian coordinate system. A brick is a $1 \times 1 \times 2020$ rectangular block. Based on its orientation, a brick can be parallel to the $x$, $y$, or $z$ axis. 

We denote an $x$-oriented brick by $(*, b, c)$, representing the region $[0, 2020] \times [b-1, b] \times [c-1, c]$ for integers $b, c \in \{1, 2, \dots, 2020\}$. Here, $b$ and $c$ are its fixed $y$ and $z$ components. Similarly, a $y$-oriented brick is denoted $(a, *, c)$, and a $z$-oriented brick is denoted $(a, b, *)$. 

By condition (3), each of the four $1 \times 2020$ faces of a brick must share interior points with a face of the cube or a $1 \times 2020$ face of another brick. For two faces to share 2-dimensional interior points, they must be coplanar. Thus, a face normal to a given axis can only share interior points with another face normal to the same axis.

Below we prove that at least $3030$ bricks must be placed. We divide the analysis into two cases based on the orientations present.

**Case 1: At least one orientation is entirely missing.**
Without loss of generality, assume there are no $z$-oriented bricks, meaning no bricks of the form $(x, y, *)$. Since some bricks must be placed, assume without loss of generality that there is an $x$-oriented brick $(*, b, c)$ on the layer $z=c$. 

Its $1 \times 2020$ faces normal to the $y$-axis (at $y=b-1$ and $y=b$) must be shared with the boundary of the cube or with other bricks. Since there are no $z$-oriented bricks, the only available bricks with faces normal to the $y$-axis are other $x$-oriented bricks. Thus, the brick $(*, b, c)$ can only share its $y$-normal faces with $(*, b-1, c)$ and $(*, b+1, c)$. This forces the entire layer $z=c$ to be completely filled with $x$-oriented bricks $(*, y, c)$ for all $y \in \{1, 2, \dots, 2020\}$. 

Furthermore, the faces of these bricks normal to the $z$-axis (at $z=c-1$ and $z=c$) must be shared with bricks in the adjacent layers. This forces the adjacent layers to contain bricks, and by the same logic, those layers must also be completely filled. Consequently, every layer of the cube must be completely filled, requiring $2020^2 > 3030$ bricks.

**Case 2: All three orientations are present.**
Suppose bricks of all three orientations appear, for instance $(a, b, *)$, $(*, c, d)$, and $(e, *, f)$. 

Consider a brick whose $x$-component is $a$, such as the $z$-oriented brick $(a, b, *)$. Its $1 \times 2020$ faces normal to the $x$-axis (at $x=a-1$ and $x=a$) must be shared with the cube boundary or with other bricks having faces normal to the $x$-axis. The only bricks with faces normal to the $x$-axis are $z$-oriented bricks $(x, y, *)$ and $y$-oriented bricks $(x, *, z)$, both of which have a specific $x$-component. Therefore, by condition (3), there must be a brick whose $x$-component is $a-1$ and a brick whose $x$-component is $a+1$ (unless $a=1$ or $a=2020$, where the face can be shared with the cube boundary). 

By induction, the $x$-components $1, 2, \dots, 2020$ must all appear among the placed bricks. Similarly, because $x$-oriented and $y$-oriented bricks are also present, the $y$-components and $z$-components $1, 2, \dots, 2020$ must all appear among the bricks.

Since each brick accounts for exactly two fixed components, we can bound the total number of bricks. Let $n_x, n_y, n_z$ be the number of $x$-oriented, $y$-oriented, and $z$-oriented bricks, respectively. An $x$-oriented brick provides a $y$ and a $z$ component, a $y$-oriented brick provides an $x$ and a $z$ component, and a $z$-oriented brick provides an $x$ and a $y$ component. The total number of distinct $x$-components present is bounded above by the number of bricks providing an $x$-component, which is $n_y + n_z$. Since all 2020 possible $x$-components must appear, we have:
$$n_y + n_z \ge 2020$$
Similarly, for the $y$ and $z$ components, we have:
$$n_x + n_z \ge 2020$$
$$n_x + n_y \ge 2020$$
Summing these three inequalities yields:
$$2(n_x + n_y + n_z) \ge 3 \times 2020 \implies n_x + n_y + n_z \ge 3030.$$

In both cases, the number of bricks is at least $3030$. Thus, the minimum possible number of bricks placed is $3030$.

Grading guidelines:
(Partial) 1. Made the key coplanarity observation: for two $1\times 2020$ faces to share interior points, they must be coplanar, hence a face normal to a given axis can only be supported by the cube boundary or by faces of bricks that are also normal to that axis. 2. In the “missing orientation” case (e.g. no $z$-oriented bricks), showed that an $x$-oriented brick $(*,b,c)$ forces the neighboring bricks $(*,b\pm1,c)$ (unless on the boundary), and hence forces the entire $z=c$ layer to be filled with $2020$ parallel bricks. 3. In the “all three orientations present” case, proved the propagation lemma that if some $x$-coordinate $a$ occurs as a fixed coordinate of a brick, then (unless $a=1$ or $2020$) some brick must realize $x=a-1$ and some brick must realize $x=a+1$, so by induction all $x$-coordinates $1,2,\dots,2020$ occur (and similarly for $y$ and $z$). (Almost) 1. Correctly derived that all three coordinate sets $\{1,2,\dots,2020\}$ must appear (in the all-three-orientations case) and set up the inequalities $n_y+n_z\ge2020$, $n_x+n_z\ge2020$, $n_x+n_y\ge2020$, but made an arithmetic slip or did not clearly justify why each distinct coordinate must be contributed by a distinct brick, so the final bound $n_x+n_y+n_z\ge3030$ is not fully secured. 2. Correctly handled the missing-orientation case and concluded it forces at least $2020^2$ bricks, but did not finish the all-three-orientations case (or omitted a boundary subcase in the propagation argument) needed to obtain the sharp lower bound $3030$. 3. Solution is almost complete, but made minor mistakes which are not negligible.

Construction task:
For the specific case of a $20 \times 20 \times 20$ cube (i.e., replacing 2020 with $2n$ where $n=10$), provide an explicit construction of the bricks that minimizes the total number of bricks placed.

Construction requirements:
- Output a single Python expression that evaluates to a list of tuples.
- Each element in the list must represent one brick and be a tuple of two tuples: `((x1, y1, z1), (x2, y2, z2))`, where the two inner tuples are the 1-based coordinates of the two $1 \times 1$ end-cubes of the brick.
- For example, a brick spanning the entire x-axis at y=2, z=3 would be `((1, 2, 3), (20, 2, 3))`.
- The construction must satisfy all adjacency and non-intersection constraints described in the problem.
- The number of bricks must be the absolute minimum possible for a $20 \times 20 \times 20$ cube.
- Use a single, valid Python expression (e.g., combining list comprehensions). Do not include any assignments, block statements, or non-executable text.
- Put ONLY the Python expression inside the `<construct>` block.

Reference construction:
[((2*i - 1, 2*i - 1, 1), (2*i - 1, 2*i - 1, 20)) for i in range(1, 11)] + [((1, 2*i, 2*i - 1), (20, 2*i, 2*i - 1)) for i in range(1, 11)] + [((2*i, 1, 2*i), (2*i, 20, 2*i)) for i in range(1, 11)]

Verifier code:
import sys

def verify():
    content = sys.stdin.read().strip()
    if not content:
        print("Empty input")
        return

    try:
        # Use eval to support list comprehensions as required by the instruction
        data = eval(content)
    except Exception as e:
        print(f"Failed to evaluate Python expression: {e}")
        return

    if not isinstance(data, list):
        print("Construction must be a list")
        return
    if len(data) != 30:
        print(f"Expected exactly 30 bricks, got {len(data)}")
        return

    occupied_cells = set()
    bricks = []

    # Parse and validate each brick, and check for non-intersection
    for idx, item in enumerate(data):
        if not isinstance(item, tuple) or len(item) != 2:
            print(f"Brick at index {idx} is not a tuple of two elements")
            return
        p1, p2 = item
        if not isinstance(p1, tuple) or len(p1) != 3:
            print(f"Brick at index {idx} endpoint 1 is not a 3-tuple")
            return
        if not isinstance(p2, tuple) or len(p2) != 3:
            print(f"Brick at index {idx} endpoint 2 is not a 3-tuple")
            return
        
        for val in list(p1) + list(p2):
            if not isinstance(val, int) or isinstance(val, bool):
                print(f"Coordinate {val} in brick {idx} is not an integer")
                return
            if val < 1 or val > 20:
                print(f"Coordinate {val} in brick {idx} is out of bounds (must be 1-20)")
                return

        diffs = [abs(p1[i] - p2[i]) for i in range(3)]
        if diffs.count(19) != 1 or diffs.count(0) != 2:
            print(f"Brick at index {idx} does not span exactly one full axis from 1 to 20")
            return
        
        axis = diffs.index(19)
        fixed_coords = list(p1)
        
        cells = []
        for i in range(1, 21):
            c = list(fixed_coords)
            c[axis] = i
            cells.append(tuple(c))
        
        bricks.append({
            'axis': axis,
            'fixed_coords': fixed_coords,
            'cells': cells
        })

        for c in cells:
            if c in occupied_cells:
                print(f"Intersection detected at cell {c}")
                return
            occupied_cells.add(c)
            
    # Check face adjacency constraints
    for idx, brick in enumerate(bricks):
        axis = brick['axis']
        fixed_coords = brick['fixed_coords']
        
        for d in range(3):
            if d == axis:
                continue
            for delta in (-1, 1):
                v = fixed_coords[d]
                adj_v = v + delta
                
                # If the face is on the boundary of the 20x20x20 cube, it is valid
                if adj_v < 1 or adj_v > 20:
                    continue
                
                # Otherwise, it must share a 1x1 area with another brick.
                # Since all bricks span the full length, any occupied cell in the adjacent line
                # guarantees a shared 1x1 or 1x20 face segment.
                adjacent_line_occupied = False
                for i in range(1, 21):
                    adj_cell = list(fixed_coords)
                    adj_cell[axis] = i
                    adj_cell[d] = adj_v
                    if tuple(adj_cell) in occupied_cells:
                        adjacent_line_occupied = True
                        break
                
                if not adjacent_line_occupied:
                    face_dir = ['x', 'y', 'z'][d]
                    print(f"Brick at index {idx} fails face adjacency on its {face_dir}={adj_v} face")
                    return

    print("True")

if __name__ == "__main__":
    verify()