※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 14003번 문제인 가장 긴 증가하는 부분 수열 5이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/14003
14003번: 가장 긴 증가하는 부분 수열 5
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (-1,000,000,000 ≤ Ai ≤ 1,000,000,000)
www.acmicpc.net
크기 100만의 수열이 주어질 때, LIS중 하나를 찾아 출력해주면 된다.
LIS중 하나를 역추적하기 위하여 글쓴이는 수를 입력받을 때마다 그 수로 끝나는 가장 긴 증가하는 부분수열의 이전 수가 무엇인지를 기록해두었다. 그리고, LIS를 이루는 마지막 수를 찾아 위의 기록해둔 배열을 이용하여 LIS를 역추적하였다.
(세그먼트트리로 LIS 구하기 연습2)
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<pair<int, int>> arr;
int seg[2097153];
int nth(int L, int R, int n) {
int sI = 1;
while (L < R) {
if (seg[sI * 2] < n) {
L = (L + R) / 2 + 1;
sI = sI * 2 + 1;
}
else {
R = (L + R) / 2;
sI = sI * 2;
}
}
return L;
}
int update(int L, int R, int qI, int qVal, int sI) {
if (R < qI || qI < L) return seg[sI];
if (L == R) return seg[sI] = qVal;
return seg[sI] = max(update(L, (L + R) / 2, qI, qVal, sI * 2), update((L + R) / 2 + 1, R, qI, qVal, sI * 2 + 1));
}
int rangemax(int L, int R, int qL, int qR, int sI) {
if (R < qL || qR < L) return 0;
if (qL <= L && R <= qR) return seg[sI];
return max(rangemax(L, (L + R) / 2, qL, qR, sI * 2), rangemax((L + R) / 2 + 1, R, qL, qR, sI * 2 + 1));
}
int inv[1000001];
int val[1000001];
int parent[1000000];
bool xcomp(pair<int, int> p1, pair<int, int> p2) {
if (p1.first != p2.first) return p1.first < p2.first;
return p1.second > p2.second;
}
bool icomp(pair<int, int> p1, pair<int, int> p2) {
return p1.second < p2.second;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int N; cin >> N;
for (int i = 0; i < N; i++) {
int x; cin >> x;
arr.push_back({ x,i });
}
sort(arr.begin(), arr.end(), xcomp);
for (int i = 1; i <= N; i++) {
val[i] = arr[i - 1].first;
arr[i - 1].first = i;
}
sort(arr.begin(), arr.end(), icomp);
int cnt = 0, last;
for (int i = 0; i < N; i++) {
int x = arr[i].first;
int temp = rangemax(1, N, 1, x, 1);
parent[x] = nth(1, N, temp);
temp++;
if (temp > cnt) {
cnt = temp;
last = x;
}
update(1, N, x, temp, 1);
}
cout << cnt << '\n';
vector<int> stk;
while (cnt--) {
stk.push_back(last);
last = parent[last];
}
while (!stk.empty()) {
cout << val[stk.back()] << ' ';
stk.pop_back();
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 10164 // C++] 격자상의 경로 (0) | 2021.07.27 |
---|---|
[BOJ 10651 // C++] Cow Jog (0) | 2021.07.26 |
[BOJ 2568 // C++] 전깃줄 - 2 (0) | 2021.07.24 |
[BOJ 18263 // C++] Milk Visits (0) | 2021.07.23 |
[BOJ 13913 // C++] 숨바꼭질 4 (0) | 2021.07.22 |