문제 링크입니다: https://www.acmicpc.net/problem/14003
Crocus님(https://www.crocus.co.kr/681) 덕분에 풀 수 있었던 문제였습니다.
O(NlogN)에 LIS의 최대 길이를 구하는 알고리즘을 통해서는 정확한 LIS 배열을 구할 수 없다는 것을 처음 알았습니다.
기존의 LIS 코드는 동일하고 pair<int, int> answer 배열과 스택을 이용해 정확한 LIS 배열을 구하는 것은 코드의 주석을 보면 이해가 될 것입니다!
#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
const int MAX = 1000000 + 1;
int N;
int arr[MAX];
int cache[MAX];
pair<int, int> answer[MAX];
stack<int> s;
int LIS(void)
{
int idx = 0;
cache[idx] = arr[0];
answer[0] = { 0, arr[0] };
for (int i = 1; i < N; i++)
{
if (cache[idx] < arr[i])
{
cache[++idx] = arr[i];
//lis가 될 수 있는 위치 정보를 first에 담고
//실제 그 값을 second에 담아준다.
answer[i] = { idx, arr[i] };
}
else
{
int idx2 = lower_bound(cache, cache + idx, arr[i]) - cache;
cache[idx2] = arr[i];
answer[i] = { idx2, arr[i] };
}
}
return idx + 1;
}
int main(void)
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for (int i = 0; i < N; i++)
cin >> arr[i];
int result = LIS();
cout << result << "\n";
/*
실제 lis 배열을 구하는 알고리즘을 보자
예를들면 다음과 같다.
1 6 2 5 7 3 5 6인 경우
ans배열에는 다음과 같이 들어간다.
first :: 0 1 1 2 3 2 3 4
second :: 1 6 2 5 7 3 5 6
이 값을 first를 기준으로 뒤에서 부터 조사해오면
first가 4일때 (6) - > first가 3일때 (5) -> first가 2일때 (3)
-> first가 1일때 (2) -> first가 0일때(1)이다.
이것을 스택에 담아 역출력하면 1,2,3,5,6이라는 실제 배열을 구할 수 있다.
*/
//출처: https://www.crocus.co.kr/681 [Crocus]
int num = result - 1;
for(int i=N-1; i>=0; i--)
if (answer[i].first == num)
{
s.push(answer[i].second);
num--;
}
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
cout << "\n";
return 0;
}
개발환경:Visual Studio 2017
지적, 조언, 질문 환영입니다! 댓글 남겨주세요~
'알고리즘 > BOJ' 카테고리의 다른 글
백준 2568번 전깃줄-2 (0) | 2019.01.24 |
---|---|
백준 14002번 가장 긴 증가하는 부분 수열 4 (0) | 2019.01.24 |
백준 2565번 전깃줄 (0) | 2019.01.24 |
백준 5015번 ls (0) | 2019.01.24 |
백준 4383번 점프는 즐거워 (0) | 2019.01.24 |