본문 바로가기
알고리즘/백준

[BOJ 11054] 가장 긴 바이토닉 부분 수열(c++)

by umdoyun 2025. 11. 27.
728x90

https://www.acmicpc.net/problem/11054

 

문제 개요

수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다. 수열 A가 주어졌을 때, 그 수열의 부분 수열 중 가장 긴 바이토닉 수열의 크기를 구해야 한다.

(1 <= N <= 1,000)

(1 <= A <= 1,000)

 

문제 풀이

https://doyun98.tistory.com/112

 

[알고리즘] LIS(최장 증가 부분 수열)

LIS(Longest Increasing Subsequence)란?주어진 수열에서 순서를 유지하며 크기가 증가하는 부분 수열 중 가장 긴 것을 의미합니다.아래와 같은 수열이 있습니다.102010302050이 수열의 LIS는 아래와 같고 크기

doyun98.tistory.com

양방향의 LIS를 모두 구하여 해결하였다. LIS를 구현하며 각 요소마다의 부분 수열의 크기를 저장하고, n - 1부터 0까지의 반대 방향으로도 LIS를 구하며 크기를 갱신하였고, 그 중 가장 큰 값을 찾아 가장 큰 바이토닉 수열의 크기를 찾았다. 문제에서는 N이 1도 가능하기 때문에 따로 처리가 필요하였는데, 이 때문에 트러블 슈팅이 오래 걸렸다.

 

코드

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int n, res = 1;
vector<int> arr;
int dp[10010], lis[1001], r_lis[1001];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	arr.reserve(n);
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		arr.push_back(x);
	}
	lis[0] = arr[0];
	int size = 1;
	dp[0] = 1;
	for (int i = 1; i < n; i++) {
		if (lis[size - 1] < arr[i]) {
			lis[size] = arr[i];
			dp[i] = ++size;
		}
		else {
			int pos = lower_bound(lis, lis + size, arr[i]) - lis;
			lis[pos] = arr[i];
			dp[i] = pos + 1;
		}
		res = max(res, dp[i]);
	}
	size = 1;
	r_lis[0] = arr[n - 1];
	for (int i = n - 2; i >= 0; i--) {
		if (r_lis[size - 1] < arr[i]) {
			r_lis[size] = arr[i];
			dp[i] += size++;
		}
		else {
			int pos = lower_bound(r_lis, r_lis + size, arr[i]) - r_lis;
			r_lis[pos] = arr[i];
			dp[i] += pos;
		}
		res = max(res, dp[i]);
	}
	cout << res;
	return 0;
}

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ 17779] 게리맨더링2 (c++)  (0) 2025.12.03
[BOJ 5588] 별자리 찾기(c++)  (0) 2025.12.02
[BOJ 1517] 버블소트(c++)  (0) 2025.11.13
[BOJ 17407] 괄호 문자열과 쿼리(c++)  (1) 2025.11.12
[BOJ 2325] 개코전쟁(c++)  (0) 2025.10.29