문제
벽
서로 다른 두 쿼리(min, max)를 처리하는 문제입니다.
풀이
세그먼트 트리의 노드에 각 구간에 적용될 min, max쿼리를 저장해둡니다.
그리고 이 쿼리 값(height)들을 minLazy, maxLazy라고 합시다.
maxLazy < minLazy일 때 쿼리의 적용 순서가 관계없음을 이용해야 이 문제를 풀 수 있습니다. 관계없는 이유는 여담에서 증명해 보이겠습니다.
모든 노드는 초깃값으로 maxLazy = 0, minLazy = INF를 갖습니다.
어떤 노드가 maxLazy < minLazy를 만족한다고 합시다.
max쿼리로 max값이 들어오게 되면
- max < maxLazy인 경우
아무 영향도 주지 않습니다. 따라서 무시합니다. - maxLazy < max < minLazy인 경우
maxLazy = max로 값을 바꿔줍니다. - minLazy < max인 경우
maxLazy = max로, minLazy = INF로 바꿔줍니다.
위 과정을 다르게 쓰면
maxLazy = max(maxLazy, max)
minLazy = max(minLazy, max)
입니다.
같은 방식으로 min쿼리가 들어오면
maxLazy = min(maxLazy, min)
minLazy = min(minLazy, min)
입니다.
어떤 쿼리가 들어오든 항상 maxLazy < minLazy임을 알 수 있습니다.
1 |
|
lazy값을 자식으로 전파할 때는 순서 상관없이 전파해 주면 됩니다. 항상 maxLazy < minLazy이기 때문에 순서를 신경쓰지 않아도 됩니다.
1 |
|
모든 쿼리가 끝나고, 벽의 값을 찾을 때는 리프노드의 maxLazy값을 찾으면 됩니다.
min(max(0, maxLazy), minLazy) = maxLazy이기 때문입니다.
1 |
|
이외에는 다른 느리게 갱신되는 세그먼트 트리처럼 구현해주면 됩니다.
코드
Node클래스와 Wall클래스를 만들었습니다. 세그먼트 트리인 Wall클래스의 private부분을 보시면 됩니다.
1 |
|
여담
maxLazy < minLazy일 때 쿼리의 적용 순서가 관계없음을 증명해 보겠습니다.
쿼리를 적용하기 전의 벽의 높이가 height였다고 합시다.
max(min(height, minLazy), maxLazy)와
min(max(height, maxLazy), minLazy)의 값이 같은지 보면 됩니다.
- height < maxLazy인 경우
max(height, maxLazy) = maxLazy min(maxLazy, minLazy) = maxLazy
따라서 height = 0일 때 maxLazy인 이유를 알 수 있습니다. 2. maxlazy < height < minLazy인 경우 max(height, maxLazy) = height min(height, minLazy) = height 3. minLazy < height인 경우 max(minLazy, maxLazy) = minLazy min(height, minLazy) = minLazy
따라서 maxLazy < minLazy이면 쿼리의 적용 순서는 상관이 없습니다.