문제 링크 - https://www.acmicpc.net/problem/12015
12015번: 가장 긴 증가하는 부분 수열 2
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)
www.acmicpc.net
문제 설명 |
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다.
둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)
첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.
아이디어 |
lower bound를 이용하여 최장 증가 부분 수열의 길이를 구할 수 있습니다.
이때, lower bound는 특정 값의 시작 위치를 찾는 알고리즘인데요.
찾고자 하는 값 이상의 값이 처음으로 나타나는 위치를 말합니다.
예를 들어 1,3,5,5,7이라는 수열이 있을 때 lower bound(5)는 5이상의 값이 처음으로 나타나는 빨간색 부분을 의미합니다.
1,3,5,5,7
수열에서 현재 수를 a라고 했을 때 a가 벡터의 마지막 값보다 크면 벡터에 삽입하고
a가 벡터의 마지막 값보다 작으면 lower bound를 해서 나온 index위치의 값을 a로 교체할 것입니다.
최종적으로 만들어진 벡터의 길이가 최장 증가 수열의 길이가 될 것입니다.
그러나 lower bound만으로 문제를 풀면 LIS의 값을 직접 구할 수는 없다는 점을 기억하셔야 합니다!
(lower bound는 이분탐색을 기반으로 알고리즘을 구현할 수 있지만 본 소스코드에선 C++ STL을 활용했습니다.)
소스코드 |
#include <bits/stdc++.h>
using namespace std;
int arr[1000001];
vector<int>v;
int main()
{
int N; scanf("%d %d",&N,&arr[0]);
v.push_back(arr[0]);
for(int i=1;i<N;i++)
{
scanf("%d",&arr[i]);
if(v.back()<arr[i])
{
v.push_back(arr[i]);
}
else
{
int index=(lower_bound(v.begin(),v.end(),arr[i])-v.begin());
v[index] = arr[i];
}
}
printf("%d",v.size());
}
이 코드를 응용하여 LIS와 관련된 많은 문제를 풀 수 있을 것입니다.
비슷한 문제
- 1365번 꼬인 전깃줄 (풀이 링크 : https://nomadsjh.tistory.com/67)
- 2352번 반도체 설계
- 1818번 책정리
- 14003번 가장 긴 증가하는 부분 수열(풀이 링크 : https://nomadsjh.tistory.com/68)
등등등...
감사합니다!
'프로그래밍 > Baekjoon & Codeup' 카테고리의 다른 글
[백준] 14003번 가장 긴 증가하는 부분 수열5 문제 풀이(c++) (2) | 2024.03.29 |
---|---|
[백준] 1365번 꼬인 전깃줄 문제 풀이(c++) (0) | 2024.03.28 |
[백준] 10026번 적록색약 문제 풀이(DFS) (1) | 2023.12.12 |
[백준] 9735번 삼차 방정식 풀기 문제풀이 (0) | 2023.12.11 |
[백준] 11286번 절댓값 힙 문제풀이 (0) | 2023.12.11 |