알고리즘/BOJ

백준 14003번 가장 긴 증가하는 부분 수열 5

꾸준함. 2019. 1. 24. 20:00

문제 링크입니다: 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