문제 링크
- http://icpc.me/16232
사용 알고리즘
- 세그먼트 트리
시간복잡도
- $O(N \log^2 N)$
풀이
$A_i \leq B_i$이기 때문에 $N$개의 사건에 의한 멘탈 변화량은 $N+1$가지입니다. 가능한 케이스가 $2^N$이 아닌 $N+1$라는 점을 이용해 문제의 풀이를 고민해볼 수 있습니다.
각 사건을 두 순서쌍 $(-\infty, A_i), (K_i, B_i)$으로 표현합니다. 이는 해당 사건 이전의 멘탈이 $K_i$ 이상이라면 $B_i$만큼 변하고, $-\infty$ 이상이라면 $A_i$만큼 변한다는 것을 의미합니다.
각 사건을 두 순서쌍으로 표현한다면, 사건 $(-\infty, A_i), (K_i, B_i)$와 $(-\infty, A_j), (K_j, B_j)$를 연달아 거치는 것은 세 개의 순서쌍 $(-\infty, A_i+A_j)$, $(K_i, B_i + A_j)$, $(K_j, A_j + B_j)$로 표현할 수 있습니다. ($K_i \leq K_j$)
이를 이용해 연속한 몇 개의 사건을 연달아 거치는 경우를 세그먼트 트리를 이용해 구할 수 있습니다. 세그먼트 트리의 리프 정점에서 각 사건을 관리하고, 내부 정점의 값은 Merge Sort Tree처럼 두 자식을 합치는 것으로 구할 수 있습니다.
세그먼트 트리를 전처리했다면, 사건 $i$가 없었을 때의 최종 상태를 구하는 것은 $\text{Query}(1, i-1)$과 $\text{Query}(i+1, N)$을 합친 결과가 됩니다.
$\text{Query}(l, r)$함수를 구현하는 것은, 구간 $[l, r]$을 나타내는 세그먼트 트리의 정점을 모두 구한 뒤, 차례대로 upper_bound
등의 함수를 이용해 멘탈 변화를 반영하면 됩니다.
전체 코드
1 |
|