문제 링크
- http://icpc.me/15864
문제 출처
- 2018 Baltic OI Day2 1번
사용 알고리즘
- 세그먼트 트리 + 레이지
- 슬라이딩 윈도우
시간복잡도
- $O(M \log M + M \log N)$
풀이
어떤 선분 $l_1$이 $l_2$에 완전히 포함된다면, $l_1$은 $l_2$와 다른 색을 배정해주면 되기 때문에 $l_1$을 없애고 생각해도 됩니다. KOI 2014 버스노선처럼 Sliding Window를 이용해 다른 선분에 완전히 포함되는 선분을 제거하고, 어떤 선분에 포함되는지만 기록합시다. (calc_elimination
함수 참고)
각 구간은 최소 한 개 이상의 선분으로 덮여있기 때문에, 어떠한 선분에도 포함되지 않는 선분들만 남겨놓은 다음 정렬하면 아래 그림처럼 나오게 됩니다.
만약 정답이 존재한다면 아래 그림처럼 색을 교차해서 놓았을 때 항상 정답이 나온다는 것을 알 수 있습니다.
어떠한 선분에도 포함되지 않은 선분의 개수를 K라고 합시다.
K가 짝수라면 위 그림처럼 색을 교차하게 놓아서 확인하면 끝날텐데, 홀수라면 약간 까다롭습니다.
K = 5라면 아래 5가지 경우를 모두 확인해야 합니다.
1 |
|
K가지 경우를 Naive하게 확인해주면 서브태스크 1, 2, 3을 해결해 55점을 받을 수 있습니다.
위에서 작성한 5가지 경우를 잘 보면, 어떤 i번째 비트열과 i-1번째 비트열은 비트 1개 밖에 차이가 나지 않는다는 것을 알 수 있습니다. K가지 경우를 모두 확인할 때 각 선분의 색깔을 1번만 바꿔도 된다는 것을 알 수 있습니다.
Segment Tree + Lazy Propagation을 사용해 구간의 최솟값을 관리하면 선분이 잘 덮여있는지 빠르게 확인해줄 수 있습니다.
선분을 정렬하고 필요 없는 선분을 제거하는데 $O(M \log M)$만큼 걸리고, 정답이 존재하는지 확인하는데 $O(M \log N)$이 걸리므로 문제를 해결할 수 있습니다.
전체 코드
1 |
|