문제 링크
- http://icpc.me/16791
문제 출처
- JOIOC 2018 1번
사용 알고리즘
- Segment Tree
- Lazy Propagation
시간복잡도
- $O((N+Q) \log N)$
풀이
Subtask 2 (38점)
집합 $S_i$를 $A_i$보다 앞에 있으면서 더 큰 수들의 집합($j < i ∧ A_j > A_i$)으로 정의합시다.
$S_i$의 크기가 0보다 크다면, $A_i$는 한 번의 pass를 통해 한 칸 앞으로 이동합니다. $S_i$의 크기가 0이라면 $A_i$는 적절히 뒤로 이동합니다. 그러므로 문제의 정답은 $\max(\vert S_i \vert)$입니다.
좌표압축을 한 뒤, 각 쿼리를 Fenwick Tree를 이용해 $O(N \log N)$에 처리해주면 총 $O(NQ \log N)$으로 38점을 받을 수 있습니다.
Full Solution (100점)
점 $(i, A_i)$를 좌표 평면에 찍어보면, Convex Hull의 오른쪽 아래에 있는 점만 정답($\vert S_i \vert$의 최댓값)이 될 수 있습니다. 그리고 이런 점에 대해서는 $\vert S_i \vert = i - $ ($A_i$보다 작은 원소의 개수)가 만족합니다.
나머지 점들에 대해서는 $\vert S_i \vert > i - $ ($A_i$보다 작은 원소의 개수) $\geq i - $ ($A_i$보다 작거나 같은 원소의 개수)입니다.
그러므로 쿼리가 주어질 때마다 $\vert S_i \vert$대신 ($i - $ ($A_i$보다 작은 원소의 개수))를 관리해도 충분합니다.
$i$는 상수이므로 ($A_i$보다 작은 원소의 개수)만 잘 관리해주면 됩니다.
배열에서 어떤 수 $x$가 빠지면 $x$보다 큰 $A_i$에 대해서, $A_i$보다 작은 원소의 개수가 1 증가합니다.
배열에 어떤 수 $x$가 추가되면 $x$보다 큰 $A_i$에 대해서, $A_i$보다 작은 원소의 개수가 1 감소합니다.
$A_x$를 $v$로 바꾸는 쿼리는 배열에서 $A_x$를 삭제하고 $v$를 추가하는 것으로 생각할 수 있고, 각 연산은 임의의 구간에 1을 더하거나 빼는 것으로 생각할 수 있습니다.
그러므로 Segment Tree와 Lazy Propagation을 사용해서 $O((N+Q) \log N)$에 문제를 해결할 수 있습니다.
전체 코드
1 |
|