DOJ logoDOJ
문제
최근 추가된 문제들저장한 문제
카테고리DLC대회그룹팀게시판
랭킹
문제 풀이 랭킹스트릭 랭킹DOJ Power 랭킹
현황
문제 제안로그인회원가입
DOJ logoDOJ

OI 서브태스크 채점, Elo 레이팅, Discord 인증을 갖춘 커뮤니티 온라인 저지.

문제
문제 목록카테고리
커뮤니티
대회랭킹게시판공지사항외부 대회 개최이용 안내
계정
로그인회원가입채점 현황
정책
이용약관DLC 이용 규칙개인정보 처리방침API 사용 설명서언어별 채점 환경대회 순위 보상레이팅과 퍼포먼스
© 2026 DOJ
모든 권리 보유
해설

뚱뚱한 수열

문제로 돌아가기

해설

AiA_iAi​에서 끝나는 가장 긴 증가하는 부분수열의 길이를 AiA_iAi​의 레벨 LiL_iLi​라 하고, K=max⁡LiK = \max L_iK=maxLi​라 하자. 모든 LiL_iLi​는 잘 알려진 lower\_bound 방식의 LIS 알고리즘으로 O(Nlog⁡N)O(N \log N)O(NlogN)에 구할 수 있다.

관찰 1. 길이 KKK인 증가하는 부분수열의 kkk번째 원소는 레벨이 정확히 kkk이다. 앞의 kkk개 원소가 증가하는 부분수열을 이루므로 레벨은 kkk 이상이다. 레벨이 kkk보다 크다면 그 뒤의 개 원소를 이어 붙여 길이가 보다 긴 증가하는 부분수열을 만들 수 있으므로 모순이다.

관찰 2. 레벨이 같은 원소들을 인덱스 순으로 나열하면 값이 감소하지 않는다. j<ij < ij<i, Lj=LiL_j = L_iLj​=Li​인데 라면 를 뒤에 붙일 수 있으므로 이 되어 모순이다.

관찰 3. 위 레벨부터 가장 큰 값을 고르면 된다. 다음과 같이 gK,gK−1,⋯ ,g1g_K, g_{K-1}, \cdots, g_1gK​,gK−1​,⋯,g을 정한다.

  • gKg_KgK​는 레벨 KKK인 원소 중 가장 앞에 있는 것, 즉 값이 가장 큰 것이다.
  • gkg_kgk​ (k<K)는 레벨 인 원소 중 값이 보다 작은 것들 가운데 가장 앞에 있는 것이다. 관찰 2에 의해 이것은 그중 값이 가장 큰 원소이다.

gk+1g_{k+1}gk+1​의 레벨이 k+1k+1k+1이므로, gk+1g_{k+1}g보다 앞에 있으면서 값이 더 작은 레벨 원소가 존재한다. 는 그런 원소들 중 가장 앞에 있으므로 인덱스도 자동으로 보다 앞이다. 따라서 는 길이 인 증가하는 부분수열이다.

이제 임의의 길이 KKK인 증가하는 부분수열 h1,h2,⋯ ,hKh_1, h_2, \cdots, h_Kh1​,h2​,⋯,h를 생각하자. 관찰 1에 의해 의 레벨은 이다. 부터 내려가며 임을 보인다. 는 의 정의에서 바로 나온다. 이라면 이고, 는 레벨 이면서 보다 작은 값 중 최댓값이므로 이다.

따라서 모든 kkk에 대해 hk≤gkh_k \leq g_khk​≤gk​이고, ggg가 뚱뚱한 수열이다. 합이 같다면 모든 원소가 같아야 하므로 뚱뚱한 수열의 원소 값은 항상 유일하다.

구현. 원소들을 레벨별로 인덱스 순서를 유지하며 모은다. 각 레벨의 목록을 앞에서부터 훑으며 값이 gk+1g_{k+1}gk+1​보다 작은 첫 원소를 찾으면 되고, 각 목록을 한 번씩만 훑으므로 이 부분은 O(N)O(N)O(N)이다.

int bound = INT_MAX;
for (int k = K - 1; k >= 0; k--) {
    int p = st[k];
    while (a[ord[p]] >= bound) p++;
    pick[k] = a[ord[p]];
    bound = pick[k];
}

전체 시간복잡도는 O(Nlog⁡N)O(N \log N)O(NlogN)이다. 합은 최대 약 101510^{15}1015이므로 64비트 정수를 써야 한다.

뒤에서부터 훑으며 처음 만나는 원소를 고르는 일반적인 LIS 역추적은 각 레벨에서 가능한 가장 작은 값을 고르므로 틀린다. 증가가 강증가라는 점에도 주의해야 한다. lower\_bound 대신 upper\_bound를 쓰면 같은 값이 있는 입력에서 틀린다.

서브태스크별 풀이.

  • 서브태스크 1: 모든 부분수열을 확인한다. O(2NN)O(2^N N)O(2NN).
  • 서브태스크 2: (길이,합)(\text{길이}, \text{합})(길이,합)의 사전순 최댓값을 상태로 두는 O(N2)O(N^2)O(N DP와 역추적.

Solution written by ClaudeOpus5.5

K−kK-k
K−k
KKK
Aj<AiA_j < A_i
Aj​<Ai​
AiA_iAi​
AjA_jAj​
Li≥Lj+1L_i \geq L_j + 1Li​≥Lj​+1
1
​
k < K
k<K
kkk
gk+1g_{k+1}gk+1​
k+1
​
kkk
gkg_kgk​
gk+1g_{k+1}gk+1​
g1,g2,⋯ ,gKg_1, g_2, \cdots, g_Kg1​,g2​,⋯,gK​
KKK
K
​
hkh_khk​
kkk
k=Kk = Kk=K
hk≤gkh_k \leq g_khk​≤gk​
hK≤gKh_K \leq g_KhK​≤gK​
gKg_KgK​
hk+1≤gk+1h_{k+1} \leq g_{k+1}hk+1​≤gk+1​
hk<hk+1≤gk+1h_k < h_{k+1} \leq g_{k+1}hk​<hk+1​≤gk+1​
gkg_kgk​
kkk
gk+1g_{k+1}gk+1​
hk≤gkh_k \leq g_khk​≤gk​
2
)
  • 서브태스크 3: 같은 DP를 값마다 하나씩 관리한다. 값이 xxx인 원소는 값이 xxx보다 작은 상태들만 보면 되므로 O(100N)O(100N)O(100N)이다.
  • 서브태스크 4: 위의 풀이. 좌표 압축 후 펜윅 트리로 (길이,합)(\text{길이}, \text{합})(길이,합)의 사전순 최댓값을 관리해도 O(Nlog⁡N)O(N \log N)O(NlogN)에 해결된다.