Q×Q(1≤Q≤100,000)그리드 상에 있는 P(1≤P≤500)명의 사람의 현재 위치와 이동 방향이 주어졌을 때,
가장 많은 사람의 진행 방향과 겹치는 점의 위치를 찾는 문제이다.
편의상 각 사람은 하나의 반평면이라고 생각하면 된다:
예를 들어 북쪽을 향하고 있을 경우 $y > y_0$ 인 모든 점이 해당 사람의 진행 방향에 있다고 할 수 있고,
동쪽을 향하고 있을 경우 $x > x_0$ 인 모든 점이 해당 사람의 진행 방향에 있다고 할 수 있다.
풀이는 가로 반평면과 세로 반평면을 따로 고려함으로써 각각 $y$와 $x$좌표를 알아낼 수 있다는 것을 떠올리면 간단하다.
우선 가로 반평면을 해결하는 방법을 살펴보자. 이는 간단한 스윕 라인1을 통해 해결할 수 있다.
북쪽을 바라보는 사람을 이벤트 $(y_0 + 1, +1)$으로 나타낼 수 있고,
같은 방법을 이용해서 남쪽을 바라보는 사람 역시 $(y_0, -1)$으로 나타낼 수 있다.
이제 각 이벤트를 처리하면서 가장 많은 사람의 진행 방향과 겹치는 점을 선택하면 끝!
오딘이 $0$번째 날에 6개의 링을 각각 $r_1, r_2, …, r_6$개 가지고 있다고 하자($r_i≤100$).
$i$번째 날이 될 때마다, $i|j$, 즉 $i$의 약수인 $j$번째 링이 두 배로 늘어난다.
따라서 $i$번째 날의 각 링의 개수는 각각 $r_1 \cdot 2^{\lfloor{i/1}\rfloor}, r_2 \cdot 2^{\lfloor{i/2}\rfloor}, …$개가 된다.
문제는 $r_1, …, r_6$을 모르는 상태에서 $i$번째 날에 오딘이 가지고 있는 모든 링 개수의 합($\mathrm{mod~} 2^{63}$)을 묻는 질문을 통해 $r_1, …, r_6$을 알아내는 것이다.
풀이의 아이디어는 각 $r_i$가 100보다 작음을 이용, 128진법과 비슷한 아이디어를 통해 합으로부터 각 링의 개수를 분리하는 것이다.
예를 들어 210일 째에 오딘이 가지고 있는 링의 개수를 풀어 쓰면 다음과 같이 표현할 수 있다:
지수를 살펴보면 각각의 차이가 7 이상이기 때문에 합으로부터 $r_4, r_5, r_6$을 얻어낼 수 있다.
마찬가지로 42일 째의 링 개수는 다음과 같이 표현 가능하다.
다행히 이미 $r_4, r_5, r_6$을 알고 있으므로, 아까와 똑같은 방법을 통해 나머지 링의 개수도 구할 수 있다.
N(1≤N≤100,000)종류의 검이 각각 여러 자루씩 존재하고,
각 종류별로 찰스와 데릴라가 각각의 검을 선택했을 때의 공격력이 주어진다.
찰스와 데릴라는 각각 자신의 공격력이 최대가 되는 검을 선택한다고 할 때,
선택할 수 있는 검의 종류를 $[L, R]$ 구간으로 제한해서 둘의 공격력 차이가 K이하가 되도록 하는 경우의 수를 구해보자.
보자마자 히스토그램에서 가장 큰 직사각형 찾기가 떠오르는 문제이다.
이를 해결하는 방법에는 여러 가지가 있지만,
여기선 구현은 조금 복잡하지만 아이디어가 간단한 방법인 바이너리 서치를 이용한 풀이를 살펴보자.
구간이 주어졌을 때, 찰스와 데릴라는 각각 가장 큰 공격력($C_i, D_i$)을 갖는 검을 고르게 된다.
이 사실을 이용해서 각각의 검이 찰스(혹은 데릴라)에게 최대의 공격력을 주는 구간을 따로 고려하면 모든 답의 후보를 살펴볼 수 있다.
다음의 테스트 케이스를 살펴보자:
5 4 # K = 4
2 4 4 0 5 # C_i
2 4 4 4 1 # D_i
여기서 각각의 검이 찰스에게 최대의 공격력을 주는 구간은 다음과 같다(각각의 수는 모두 인덱스를 나타낸다).
왼쪽의 각 구간 별 중괄호 표현은 각 검이 구간 내의 최댓값인 가장 큰 구간을 나타낸다.
이를 구할 때 바로 바이너리 서치를 이용하게 되는데,
검 $i$에 대한 구간을 고려할 때, $[i, j]$ 구간의 최댓값이 $C_i$ 이하라면
$j < k$인 $[i, k]$ 구간의 최댓값 역시 $C_i$ 이하가 되기 때문에
바이너리 서치로 $i$를 중심으로 했을 때 (1)오른쪽 끝과 (2)왼쪽 끝을 따로 구할 수 있다.
이 구간을 $L_i, R_i$라고 하자.
이제 $C_i - K ≤ \mathrm{max}(\{D_j \| L’≤j≤R’\}) ≤ C_i + K$를 만족하는
$L_i ≤ L’ ≤ i ≤ R’ ≤ R_i$ 쌍의 개수를 구하면 검 $i$가 속하는 모든 가능한 구간의 개수를 구할 수 있다.
여기선 부등호의 양 변을 따로 계산하면 편리한데, 우선 $D_j ≤ C_i + K$를 만족하는 $j$의 최대 범위를 아까와 같은 방식으로 찾고,
이를 $L^+, R^+$라고 하자. 그 다음 $D_j ≥ C_i - K$를 만족하는 최대 범위를 찾아 $L^-, R^-$라고 하면 (그런 구간이 존재할 경우)
$L_i ≤ L^+ ≤ L^- ≤ i ≤ R^- ≤ R^+ ≤ R_i$가 되고, 이로부터 $L’ = \{L^+, …, L^-\}$, 그리고
$R’ = \{R^-, …, R^+\}$를 찾아 $i$를 중심으로 하는 구간의 개수 $\|L’\| \cdot \|R’\|$를 얻을 수 있다.
여기까진 어렵지 않게 떠올릴 수 있지만, 실제로 구현할 때에는 특정 구간의 최댓값을 빠르게 구하는 구간 최댓값 쿼리2를 이용해야 하고, 같은 공격력을 갖는 검이 여럿 있을 경우 중복되는 구간을 세지 않도록(위의 예제를 보자) 신경써서 구현해야 해서 대회 시간에 해결하기에는 어려운 문제라고 느꼈다.