[백준] [C++] 14003번 가장 긴 증가하는 부분 수열 5 (bsearch)
2021. 7. 2. 17:17ㆍ알고리즘/백준
1. 문제
14003번: 가장 긴 증가하는 부분 수열 5 (acmicpc.net)
2. N log N
O (N lg N) 만에 lis를 구하는 방법
키워드는 "증가"
인덱스 0 부터 차례대로 수열의 수들을 스택에 담는다.
이때 top보다 더 작은 수가 들어온다는것은 lis가 연결되지 않는다는 의미이다.
하지만 이 원소를 포함한 lis가 만들어 질 수 도 있다.
따라서 이 원소를 스택안에서 이것보다 크지만 최소인 원소랑 바꾼다 (lower bound)
3. 추적
스택에 원소를 담을때 이어지는 이전 수의 인덱스를 같이 저장하게되면
마지막 lis가 완성되고 스택의 top에서부터 같이 저장한 이 인덱스를 따라 올라가면
실제 lis를 구할 수 있다.
4. 코드 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int N;
vector<int> seq;
vector<vector<pair<int, int>>> lls; //first => value, second => idx
void insert(int x) {
int j = -1;
if(lls.empty() || lls.back().back().first < x) {
if(!lls.empty()){
j = lls.back().size() - 1;
}
lls.push_back({{x, j}});
}
else {
int lo = -1, hi = lls.size();
while(true) {
int mid = (lo + hi)/2;
if(lo + 1 == hi) {
if(hi != 0) {
j = lls[hi-1].size() -1;
}
lls[hi].push_back({x, j});
break;
}
if(lls[mid].back().first < x) {
lo = mid;
}
else {
hi = mid;
}
}
}
}
void print(int i, int j) {
if(i == -1) return;
print(i - 1, lls[i][j].second);
cout<<lls[i][j].first<<" ";
}
void solve() {
for(int i = 0; i < N; i++) {
insert(seq[i]);
}
cout<<lls.size()<<"\n";
print(lls.size() -1, 0);
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>N;
seq = vector<int>(N);
for(int i = 0; i < N; i++) {
cin>>seq[i];
}
solve();
}
|
cs |
5. 코드 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int N;
vector<int> seq;
vector<vector<pair<int, int>>> lls; //first => value, second => idx
void insert(int x, int idx) {
if(lls.empty() || lls.back().back().first < x) {
lls.push_back({{x, idx}});
}
else {
int lo = -1, hi = lls.size();
while(true) {
int mid = (lo + hi)/2;
if(lo + 1 == hi) {
lls[hi].push_back({x, idx});
break;
}
if(lls[mid].back().first < x) {
lo = mid;
}
else {
hi = mid;
}
}
}
}
void print(int idx, int seqIdx) {
if(idx == -1) return;
int lo = -1, hi = lls[idx].size();
while(true) {
int mid = (lo + hi)/2;
if(lo + 1 == hi) {
seqIdx = lls[idx][mid].second;
break;
}
else if(lls[idx][mid].second < seqIdx) {
lo = mid;
}
else {
hi = mid;
}
}
print(idx -1 , seqIdx);
cout<<seq[seqIdx]<<" ";
}
void solve() {
for(int i = 0; i < N; i++) {
insert(seq[i], i);
}
cout<<lls.size()<<"\n";
print(lls.size() - 1, N - 1);
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>N;
seq = vector<int>(N);
for(int i = 0; i < N; i++) {
cin>>seq[i];
}
solve();
}
|
cs |
'알고리즘 > 백준' 카테고리의 다른 글
[백준] [C++] 9466번 텀 프로젝트 (dfs, scc) (0) | 2021.07.04 |
---|---|
[백준] [C++] 7579번 앱 (dp, knapsack, bsearch) (0) | 2021.07.03 |
[백준] [C++] 2623번 음악프로그램 (DFS, 위상정렬, 사이클, DAG) (0) | 2021.07.02 |
[백준] [C++] 2473번 세 용액 (bsearch, two pointer) (0) | 2021.07.01 |
[백준] [C++] 1208번 부분수열의 합2 (조합, 중간에서 만나기) (0) | 2021.06.30 |