문제 링크
- http://icpc.me/2867
문제 출처
- COCI 2010/2011 Contest #3 5번
사용 알고리즘
- Stack
시간복잡도
- O(n)
풀이
이 문제의 Naive한 풀이는 O(n3)의 시간 복잡도를 갖습니다.
이 문제에서 n은 최대 3e5이기 때문에 최소한 O(n log n)안에는 끝내야 합니다.
stack을 활용하면 O(n)만에 해결할 수 있고, O(n)이면 주어진 시간 내에 여유롭게 끝낼 수 있습니다.
이 문제는 4가지의 지표를 이용해 정답을 구합니다.
- 왼쪽에서 특정 지점까지는 내가 최댓값이다. -> A
- 왼쪽에서 특정 지점까지는 내가 최솟값이다. -> C
- 오른쪽에서 특정 지점까지는 내가 최댓값이다. -> B
- 오른쪽에서 특정 지점까지는 내가 최솟값이다. -> D
위 4가지 지표를 이용해서 특정 값이 최댓값인 구간과, 최솟값인 구간을 알 수 있습니다.
이 문제는 연속한 부분 수열의 최댓값과 최솟값을 구해서 계산하는 문제이므로 구간을 미리 구한다면 편하게 문제를 풀 수 있습니다.
현재 원소를 K번째 원소라고 가정합시다.
[A, B]범위에서는 K번째 원소가 최댓값이기 때문에 [A, K], (K, B] 범위에서 각각 하나씩 고른 값을 I, J라고 한다면 [I, J] 범위에서도 K번째 값이 최댓값입니다.
해당 경우의 수는 (K-A+1) * (B-K) 이기 때문에 정답에 K번째 원소를 (K-A+1) * (B-K)번 더해줍니다.
[C, D]범위에서도 K번째 원소가 최솟값이라는 점만 뺀다면 위의 경우와 같습니다. 다만, 정답에 K번째 원소를 (K-C+1) * (D-K)번 빼줍니다.
A, B, C, D는 스택을 이용해 쉽게 구할 수 있습니다.
A, C는 스택을 순 감소 상태로 유지하면서 쉽게 구할 수 있습니다.
B, D는 스택을 단조 증가 상태로 유지하면서 쉽게 구할 수 있습니다.
(A, C를 단조 감소 상태로 유지하고 B, D를 순 증가 상태로 유지해도 됩니다.)
원리는 이 문제(클릭)와 같습니다.
전체 코드
1 |
|