가장 긴 증가하는 부분 수열 (LIS) - 1
- LIS 길이 구하기 (dp)
- 백준 11055 가장 큰 부분 증가 수열
- LIS 길이 구하기 (이분 탐색)
- 백준 1365 꼬인 전깃줄
#include <iostream>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int dp[1001] = { 0 };
int A[1001] = { 0 };
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> A[i];
int max = 1;
dp[0] = 1;
for (int i = 1; i < n; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++)
if (A[i] > A[j] && dp[j] + 1 > dp[i])
dp[i] = dp[j] + 1;
if (max < dp[i]) max = dp[i];
}
cout << max;
return 0;
}
벡터 생성 -> 나올 수 없는 가장 작은 값을 삽입한다
벡터의 맨 뒤 원소와 A 비교
-> A 가 더 클 경우 벡터에 push_back() 해준 뒤 LIS의 길이 1 증가
-> A 가 더 작을 경우 lower_bound() 를 이용하여 최적의 자리를 찾은 뒤 그 자리의 값을 A로 교체한다
이때, 벡터에 들어있는 값이 LIS를 이루는 요소와 무관하다
수열 상에서 뒤에 위치한 원소가 앞에 위치한 원소보다 lower_bound로 탐색 된 최적의 위치가 앞에 있을 수도 있기 때문이다
예. 1 6 2 5 7 3
vt: 1
vt: 1 6
vt: 1 2
vt: 1 2 5
vt: 1 2 5 7
vt: 1 2 3 7
(LIS: 1 2 5 7)
#include <iostream>
#include <limits.h>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n;
cin >> n;
int lis = 0;
vector <int> vt;
vt.push_back(INT_MIN);
for (int i = 0; i < n; i++) {
int A;
cin >> A;
if (vt.back() < A) {
vt.push_back(A);
lis++;
}
else {
auto it = lower_bound(vt.begin(), vt.end(), A);
*it = A;
}
}
cout << lis;
return 0;
}