파게로그
[백준 12015번] LIS(최장 증가 부분 수열) 이분탐색 본문
문제 링크: 12015번 가장 긴 증가하는 부분 수열 2
https://www.acmicpc.net/problem/12015
먼저 lower bound에 대해 알아야 한다. lower bound는 처음으로 나온 key보다 큰 수의 위치를 말한다. 이는 이분탐색 과정을 조금만 응용하면 된다.
static int lowerBound(ArrayList<Integer> list, int target) {
int left = 0;
int right = list.size();
int mid;
while (left <= right) {
mid = (left+right) / 2;
if (list.get(mid) >= target)
right = mid-1;
else
left = mid+1;
}
return left;
}
배열이 아닌 리스트로 구현해 두어서 좀 보기 불편하긴 하지만... 언젠가 left > right
이 성립할 때, left
는 lower bound를 가리키고 있다. arr[mid] == key
일 때 mid+1
을 바로 반환하지 않는 것은 중복되는 원소가 있을 수 있기 때문이다.
한편 i는 배열 전체를 순회하는데, 만약 arr[i]가 list의 가장 마지막 숫자 즉 가장 큰 숫자보다 크다면 이는 arr[i]가 list의 마지막에 붙을 수 있음을 의미한다.
그렇지 않다면? 그렇다고 해서 arr[i]를 그냥 넘어가는 것이 아니라... list가 LIS를 만족하면서도 후에 다른 숫자가 들어올 수 있도록 arr[lower_bound]를 갱신된 값으로 바꾸어준다.
물론 이렇게 하면 list 자체가 LIS와 동일한 것은 아니지만, 길이는 (가장 처음에 추가한 0만 제외한다면) LIS와 동일한 것이다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
static int lowerBound(ArrayList<Integer> list, int target) {
int left = 0;
int right = list.size();
int mid;
while (left <= right) {
mid = (left+right) / 2;
if (list.get(mid) >= target)
right = mid-1;
else
left = mid+1;
}
return left;
}
static int last(ArrayList<Integer> list) {
return list.get(list.size() - 1);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
int[] arr = new int[n];
for (int i = 0; i < n; i++)
arr[i] = Integer.parseInt(st.nextToken());
ArrayList<Integer> list = new ArrayList<>();
list.add(0);
for (int i = 0; i < n; i++) {
if (arr[i] > last(list)) {
list.add(arr[i]);
continue;
} else if (arr[i] < last(list)) {
int idx = lowerBound(list, arr[i]);
list.set(idx, arr[i]);
}
}
System.out.print(list.size() - 1);
}
}
'콤퓨타 왕왕기초 > PS' 카테고리의 다른 글
[백준 2840번] 행운의 바퀴 (0) | 2021.04.13 |
---|---|
[백준 17413번] 단어 뒤집기 2 (0) | 2021.04.08 |
[백준 11053번] LIS(최장 증가 부분 수열) DP (0) | 2021.04.07 |
[백준 17298번] 오큰수 (0) | 2021.03.30 |
[백준 1074번] 재귀로 Z 모양 그리기 (0) | 2021.03.05 |
Comments