최장 증가 수열이란 주어진 수열의 부분수열중 가장 긴 증가 하는 수열을 말합니다.
예를들어, 다음과 같은 10개 원소의 수열에서
1, 3, 4, 5, 6, 9, 10의 7의 부분 수열이 가장 긴 증가 하는 수열입니다.
DP를 사용한 아이디어로서, 이분탐색을 이용하여 O(NlogN)의 시간복잡도로 해결합니다.
앞에서 부터 뒤로 O(N)으로 탐색을 하고
현재 원소의 놓여질 최적의 자리를 찾는데 이분탐색을 이용하여 O(logN)이 걸립니다.
1. 처음 벡터에 -INF를 넣어줍니다.
2. 벡터의 맨 뒤의 값보다 넣으려는 1이 크기 때문에(-INF<1) 맨뒤에 추가
3. 벡터의 맨 뒤의 값보다 넣으려는 7이 크기 때문에(1<7) 맨뒤에 추가
4. 벡터의 맨 뒤의 값보다 넣으려는 3이 작다면 lower_bound()함수를 사용하여 자기(3)보다 작은 값(1) 뒤에 넣습니다.
5. 벡터의 맨 뒤의 값보다 넣으려는 4가 크기 때문에(3<4) 맨뒤에 추가
6. 벡터의 맨 뒤의 값보다 넣으려는 2이 작다면 lower_bound()함수를 사용하여 자기(2)보다 작은 값(1) 뒤에 넣습니다.
7. 벡터의 맨 뒤의 값보다 넣으려는 8이 크기 때문에(4<8) 맨뒤에 추가
8. 벡터의 맨 뒤의 값보다 넣으려는 5이 작다면 lower_bound()함수를 사용하여 자기(5)보다 작은 값(4) 뒤에 넣습니다.
9. 벡터의 맨 뒤의 값보다 넣으려는 6이 크기 때문에(5<6) 맨뒤에 추가
10. 벡터의 맨 뒤의 값보다 넣으려는 9가 크기 때문에(6<9) 맨뒤에 추가
11. 벡터의 맨 뒤의 값보다 넣으려는 10이 크기 때문에(9<10) 맨뒤에 추가
코드는 간단합니다.
https://www.acmicpc.net/problem/2352
int n,m,ans=0; vector<int> v; int main() { scanf("%d",&n); v.push_back(-INF); for(int i=0;i<n;i++) { scanf("%d",&m); if(v.back()<m) { v.push_back(m); ans++; } else { auto it=lower_bound(v.begin(), v.end(),m); *it=m; } } printf("%d",ans); return 0; }
'IT > 알고리즘 및 자료구조' 카테고리의 다른 글
[알고리즘 정리] 그라함 알고리즘(Graham’s scan) 알고리즘 (0) | 2018.08.26 |
---|---|
[알고리즘] 구조체를 이용한 행렬의 곱 구현 (0) | 2018.08.11 |
[알고리즘 정리] 최소 신장 트리(MST, Minumum Spanning Tree) 알고리즘(프림 알고리즘) (0) | 2018.06.03 |
[알고리즘] 비트를 이용한 시프트, 논리 연산 ( <<, >>, &, |) (0) | 2018.06.02 |
[알고리즘] STL lower_bound(), upper_bound(), equal_range() (0) | 2018.06.01 |