[20260311] BOJ / D3 / LIS on Tree / 권혁준#2012
Merged
ShinHeeEul merged 1 commit intomainfrom Mar 11, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🧷 문제 링크
https://www.acmicpc.net/problem/33752
🧭 풀이 시간
300분
👀 체감 난이도
✏️ 문제 설명
정점$N$ 개인 트리가 주어진다. 각 정점에는 가중치 $v_i$ 가 달려있다.$u$ 와 $v$ 를 잇는 경로에서 만나는 정점 번호를 차례대로 기록한 수열 $P$ 에 대해,
$P$ 에서 $0$ 개 이상의 원소를 제거하여 얻은 부분 수열 $S$ 를 트리 부분 수열이라고 정의한다.
임의의 정점
트리 부분 수열$S = { s_1, s_2, \cdots, s_k }$ 에 대해,
$v_{s_1} < v_{s_2} < \cdots < v_{s_k}$ 를 만족하는 $S$ 를 증가하는 트리 부분 수열이라고 정의한다.
주어진 트리에서 증가하는 트리 부분 수열의 최대 길이를 구해보자.
🔍 풀이 방법
트리의 지름을 구할 때와 비슷하게 생각해봤다.
어떤 점의 아래로 겹치지 않는 두 경로를 합친 것이 트리의 지름의 후보가 될 수 있는 것처럼,
어떤 점의 아래로 겹치지 않는 두 LIS, LDS를 합친 것이 증가하는 트리 부분 수열의 후보가 될 수 있다.
asc[i] = 리프에서부터 i번 정점까지 도달하였을 때, i번 정점을 반드시 포함하는 LIS의 최대 길이asc2[i] = 리프에서부터 i번 정점까지 도달하였을 때, i번 정점을 반드시 포함하는 LIS의 두 번째 최대 길이dec[i] = 리프에서부터 i번 정점까지 도달하였을 때, i번 정점을 반드시 포함하는 LDS의 최대 길이dec2[i] = 리프에서부터 i번 정점까지 도달하였을 때, i번 정점을 반드시 포함하는 LDS의 두 번째 최대 길이이렇게 정의하면, 각 i마다 asc[i] + dec[i] - 1가 답의 후보가 된다.
만약, asc[i]와 dec[i]의 경로가 겹치는 경우는 asc2[i] + dec[i] - 1, asc[i] + dec2[i] - 1 중 최댓값을 택하면 된다.
다음으로는, 저 asc, asc2, dec, dec2를 효율적으로 구하는 방법을 생각해봤다.$v_i$ 보다 작은 가중치를 가지는 정점은 이미 다 처리된 상태여야 한다.
i번 정점으로 도달하는 LIS를 구하려면,
i번 정점을 루트로 하는 서브트리 내에서 asc 값이 가장 큰 정점을 하나 선택하고 거기에 +1을 해주면 되겠다고 생각했다.
-> 트리에서 업데이트 쿼리가 가능해야 하고 서브트리에 대한 max연산도 지원해야 하니까,
오일러 경로 테크닉+세그먼트 트리로 구현할 수 있다.트리의 지름을 구할 때는 경로 상의 모든 점이 지름에 기여하지만, LIS는 그렇지 않을 수도 있다.
중간에 빠져도 되는 점들이 있을 수 있기 때문에, asc[i]와 dec[i]가 i번 정점에서 사용될 수도 있고 i번 정점의 조상에서도 사용될 수 있어야 한다.
따라서
DFS+smaller to larger로 리프에서부터 올라가면서 asc, dec를 잘 합쳐주며 정답을 갱신해 나갔다.⏳ 회고
구현도 너무 복잡했고 아이디어를 떠올리는 것도 힘들었다.
손으로 반례를 못 찾겠어서 naive 정답 코드와 내 코드의 결과가 다르게 나올 때까지 무한루프로 테케를 생성해서 겨우 찾아냈다.