Loading [MathJax]/jax/output/HTML-CSS/config.js
Post

[백준] 12015번: 가장 긴 증가하는 부분 수열 2

[백준] 12015번: 가장 긴 증가하는 부분 수열 2

📌 문제

https://www.acmicpc.net/problem/12015

📌 설명

11053번: 가장 긴 증가하는 부분 수열 문제는 이중 for문을 돌며 현재 원소의 dp값은 현재 원소보다 작은 원소들의 dp값의 최댓값에 1을 더한 값이었다. 이번 문제는 위와 같은 O(N^2) 풀이로 풀게 되면 시간 초과가 발생한다. 

 LIS를 푸는 방법은 크게 두 가지가 있는데, DP를 활용한 방법과 이진 탐색을 활용한 방법이다. 이번에는 이진 탐색을 사용한다. 여러 LIS의 각 길이의 가장 작은 원소를 저장하는 배열을 선언한다. 이 배열을 arr로 하고 예를 들어보자면, arr[5] = 8은 여러 LIS 중 길이가 5인 원소 중 가장 작은 원소가 8이라는 뜻이다. LIS는 당연히 오름차순으로 정렬되어있으며, 이진 탐색을 사용할 수 있다. 즉, 전체 원소에 대하여 한 번 for문을 돌며 해당 원소보다 같거나 큰 첫 번째 원소를 해당 원소 값으로 바꾸면 된다. 만약 그러한 원소들이 없다면 배열에 삽입하면 된다.

📌 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int dp[1000000];
vector<int> who; // dp[i]의 값 중 가장 작은 수 저장

int main() {
	int n;
	cin >> n;

	vector<int> v;
	for (int i = 0;i < n;i++) {
		int x;
		cin >> x;
		v.push_back(x);
	}

	for (int i = 0;i < n;i++) {
		// 현재 원소가 LIS의 마지막 원소보다 더 큼
		int lower= lower_bound(who.begin(), who.end(), v[i]) - who.begin();

		if (lower == who.size()) {
			who.push_back(v[i]);
		}
		else {
			who[lower] = v[i];
		}
	}

	cout << who.size();
}
This post is licensed under CC BY 4.0 by the author.