※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 24834번 문제인 Shortest and Longest LIS이다.
문제는 아래 링크를 확인하자.

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

 

24834번: Shortest and Longest LIS

For each test case, print two lines with $n$ integers each. The first line is the sequence with the minimum length of the LIS, and the second line is the sequence with the maximum length of the LIS. If there are multiple answers, print any one of them. Eac

www.acmicpc.net

1이상 N이하의 서로 다른 수로 이루어지고, 서로 인접한 두 수의 대소 관계가 주어진 문자열과 같은 길이 N의 수열 중 LIS의 길이가 가장 짧은 수열과 긴 수열을 각각 구하는 문제이다.

 

주어지는 문자열에 '<'가 연속으로 최대 k회 이어지는 부분이 존재한다면(없다면 k=0으로 한다) 적어도 해당 부분에 대응되는 k+1개의 연속한 항은 증가수열을 이루게 된다. 이것이 이 수열의 LIS(중 하나)가 되게끔 항상 수열을 구성할 수 있을지를 생각해보는 것으로 Shortest LIS를 갖는 수열을 찾아낼 수 있을 것이다.

 

주어지는 문자열에 등장하는 '<'의 개수를 m개라 하자. 이 때 LIS의 길이는 m+1보다 커질 수 없다는 것을 쉽게 알 수 있다. 여기서, LIS의 길이가 m+1인 수열을 항상 구성할 수 있을지를 생각해보는 것으로 Longest LIS를 갖는 수열을 찾아낼 수 있을 것이다.

 

위와 같은 방식으로 길이의 bound를 먼저 찾아낸다면 정답에 해당하는 수열 중 하나를 찾아내는 방법은 어렵지 않게 생각해낼 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <string>
using namespace std;

void solve() {
	int slen; string s; cin >> slen >> s;
	
	// minLIS
	int mx = slen;
	int cnt = 1;
	int tmp;
	for (auto l : s) {
		if (l == '<') cnt++;
		else {
			mx -= cnt;
			tmp = mx + 1;
			while (cnt--) cout << tmp++ << ' ';
			cnt = 1;
		}
	}
	mx -= cnt;
	tmp = mx + 1;
	while (cnt--) cout << tmp++ << ' ';
	cout << '\n';

	//maxLIS
	int mn = 0;
	cnt = 1;
	for (auto l : s) {
		if (l == '>') cnt++;
		else {
			mn += cnt;
			tmp = mn;
			while (cnt--) cout << tmp-- << ' ';
			cnt = 1;
		}
	}
	mn += cnt;
	tmp = mn;
	while (cnt--) cout << tmp-- << ' ';
	cout << '\n';
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int T; cin >> T;
	while (T--) solve();
}
728x90

+ Recent posts