"""TC: O(n), SC: O(1)

아이디어:
높이 리스트 l이 주어졌다고 하자. 그리고 이 안에 있는 최대 수조 면적을 f(l)이라고 하자.

  □               □   □  
  □               □   □   □
  □ □ □   □       □ □ □ □ □
□ □ □ □   □   □ □ □ □ □ □ □
□ □ □ □ □ □ □ □ □ □ □ □ □ □
2,5,3,3,1,3,1,2,2,5,3,5,3,4
            ^
            l          


그러면 다음이 항상 성립한다.

- l의 양 끝의 값 중 작은 값 x가 앞쪽에 있었다고 해보자. x를 뺀 리스트 l`을 만든다.
    - 이때 작은 값이 뒷쪽에 있었어도 일반성을 잃지 않는다.

 │□               □   □  
 │□               □   □   □
 │□ □ □   □       □ □ □ □ □
□│□ □ □   □   □ □ □ □ □ □ □
□│□ □ □ □ □ □ □ □ □ □ □ □ □
2│5,3,3,1,3,1,2,2,5,3,5,3,4
^             ^
x             l`


- f(l)은 그렇다면
    - f(l`)이거나(즉, x를 쓰지 않았거나)
    - x를 써서 만든 수조 면적 중에 있다.

- 그런데 x는 l의 양 끝 값 중에 작은 값이므로, 아래와 같은 분석을 할 수 있다.
    1) x를 써서 만드는 수조의 높이는 아무리 높아도 x다. x보다 작아질 수는 있어도, x보다 커질 수는 없다.
    2) x를 써서 만드는 수조의 폭은 l의 다른쪽 끝에 있는 높이를 선택했을때 최대가 된다.
- 그러므로, x를 써서 만들 수 있는 수조의 최대 크기는 l의 다른쪽 끝에 있는 높이를 선택한 경우 나온다.

위의 내용을 아래의 설명을 통해 시각적으로 확인할 수 있다.

- 양 끝을 선택한 경우 x로 만들 수 있는 최대 면적이다.

 │□               □   □  
 │□               □   □   □
 │□ □ □   □       □ □ □ □ □
■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
2│5,3,3,1,3,1,2,2,5,3,5,3,4
^                         ^

- x는 그대로 둔 채 다른쪽 끝을 안쪽으로 더 이동하면 수조 높이는 동일한데 폭은 더 작아진다.

 │□               □   □  
 │□               □   □   □
 │□ □ □   □       □ □ □ □ □
■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ □ □
■│■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ □ □
2│5,3,3,1,3,1,2,2,5,3,5,3,4
^                     ^

- 심지어 x보다 작은 높이 값을 선택한 경우 수조 높이도 작아지고 폭도 작아지는 일이 일어난다.

 │□               □   □  
 │□               □   □   □
 │□ □ □   □       □ □ □ □ □
□│□ □ □   □   □ □ □ □ □ □ □
■│■ ■ ■ ■ ■ ■ □ □ □ □ □ □ □
2│5,3,3,1,3,1,2,2,5,3,5,3,4


즉, 위의 내용을 종합하면 다음을 확인할 수 있다.
- f(l) = max( (l의 양 끝 높이를 선택해서 만든 수조 넓이), f(l`) )
- 그런데 f(l`)도 f(l)을 구한 것과 같은 방식으로 구할 수 있다. 즉, 새로 만들어진 l`의 양 끝 높이 중
  짧은 쪽을 뺀 리스트 l``을 만들어서 위의 과정을 반복할 수 있다.
- 즉, f(l)은 아래의 과정을 반복하여 구할 수 있다.
    - l의 양 끝 높이를 써서 수조 넓이를 구하고, 기존 최대 넓이와 비교하여 더 큰 값을 최대 넓이에 대입한다.
    - l에서 짧은 쪽 높이를 뺀다.
    - 위 과정을 l에 아이템이 하나만 남을 때까지 반복.


SC:
- 투 포인터를 써서 l의 시작, 끝 인덱스를 관리하면 O(1).
- 수조 최대 넓이값 관리, O(1).
- 종합하면 O(1).

TC:
- 리스트의 양 끝 높이를 통해 면적 구하기, O(1).
- 포인터 이동 O(1).
- 포인터 이동시 두 포인터 사이의 거리가 1씩 항상 감소하므로 위 과정을 최대 n-2번 반복.
- 종합하면 O(n). 
"""


class Solution:
    def maxArea(self, height: List[int]) -> int:
        max_area = -1
        s, e = 0, len(height) - 1
        while s < e:
            max_area = max(max_area, (e - s) * min(height[s], height[e]))
            if height[s] > height[e]:
                e -= 1
            else:
                s += 1
        return max_area
