문제 링크
- http://icpc.me/15977
문제 출처
- 2018 KOI 고등부 3번
시간복잡도
- O(Nlg2N)
풀이
1행을 기준으로 정렬을 해봅시다.
M = 2인 경우에는 O(NlgN)만에 LIS를 구해주면 쉽게 풀 수 있습니다.
M = 2인 경우는 너무 간단하니까, M = 3인 경우의 풀이만 살펴봅시다.
첫 번째 행을 A[], 두 번째 행을 B[], 세 번째 행을 C[]라고 합시다.
A[i] < A[j] and B[i] < B[j] and C[i] < C[j]
를 만족하는 부분 수열의 최대를 구해야합니다.
이미 A[] 기준으로 이미 정렬을 했기 때문에 B[i] < B[j] and C[i] < C[j]
만 고려해주면 됩니다.
pair에 대한 LIS를 구하는 문제로 환원이 됩니다.
LIS를 세그먼트 트리로 구할 수 있듯이 pair의 LIS도 2D 세그먼트 트리로 O(Nlg2N)에 구할 수 있지만, 다른 방법을 생각해봅시다.
lis[i] = i번째로 끝나는 lis의 길이
로 정의를 하고 관찰을 해봅시다.
어떤 K에 대해, lis[i] = K를 만족하는 (B[i], C[i])쌍을 모두 모아서 보면 B[i]가 증가할수록 항상 C[i]가 감소합니다.
B[i]가 C[i]가 감소한다는 것은, 2차원 좌표 평면 상에 점을 찍었을 때 계단 모양이 나온다는 것을 의미합니다.
이런 점들은 set/map을 통해 관리해줄 수 있습니다.
lis는 최대 20만까지 set을 20만 개 만들어서 각각 점들을 관리해주면 됩니다.
lis[i] = K가 되기 위해서는 j < i and lis[j] = K-1
를 만족하는 j가 존재해야 합니다. lis는 최장 증가 부분 수열이므로 이진탐색을 통해 i보다 앞에 올 수 있으면서 lis의 값이 가장 큰 값 X를 찾아준다면, lis[i]는 X+1이 됩니다.
전체 코드
1 |
|