※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 18866번 문제인 젊은 날의 생이여이다.
문제는 아래 링크를 확인하자.
https://www.acmcipc.net/problem/18866
첫 번째 날부터 \(k\)번째 날까지의 행복도의 최솟값이 \(k+1\)번째 날부터 \(N\)번째 날까지의 행복도의 최댓값보다 크고, 첫 번째 날부터 \(k\)번째 날까지의 피로도의 최댓값이 \(k+1\)번째 날부터 \(N\)번째 날까지의 피로도의 최솟값보다 작은 \(k\)의 값 중 가장 큰 값을 구하는 문제이다.
\(k\) 이하의 날의 행복도의 최솟값 및 피로도의 최댓값은 prefix min/max를 이용해 \(O(N)\)에 계산가능함을 관찰하자. 이는 \(k\) 이상의 날의 행복도의 최댓값 및 피로도의 최솟값에도 똑같이 적용할 수 있다.
따라서 위와 같은 전처리 후 각 \(k\)에 대하여 \(k\)번째 날이 젊은 날과 늙은 날을 구분하는 기준이 될 수 있는지를 각각 \(O(1)\)에 판정해 문제를 해결할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
int N;
int H[1000002], F[1000002];
int LH[1000002], RH[1000002], LF[1000002], RF[1000002];
int ans = -1;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for (int i = 1; i <= N; i++) cin >> H[i] >> F[i];
LH[0] = 1000000007;
for (int i = 1; i <= N; i++) {
if (!H[i]) LH[i] = LH[i - 1];
else LH[i] = min(LH[i - 1], H[i]);
}
for (int i = N; i > 0; i--) {
if (!H[i]) RH[i] = RH[i + 1];
else RH[i] = max(RH[i + 1], H[i]);
}
for (int i = 1; i <= N; i++) {
if (!F[i]) LF[i] = LF[i - 1];
else LF[i] = max(LF[i - 1], F[i]);
}
RF[N + 1] = 1000000007;
for (int i = N; i > 0; i--) {
if (!F[i]) RF[i] = RF[i + 1];
else RF[i] = min(RF[i + 1], F[i]);
}
for (int i = 1; i < N; i++) {
if (LH[i] > RH[i + 1] && LF[i] < RF[i + 1]) ans = i;
}
cout << ans;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 28851 // C++] Протокол <<Судного дня>> (0) | 2024.07.11 |
---|---|
[BOJ 11968 // C++] High Card Wins (2) | 2024.07.10 |
[BOJ 11626 // C++] Physical Music (0) | 2024.07.08 |
[BOJ 11255 // C++] ITAI Virus (0) | 2024.07.07 |
[BOJ 5351 // C++] Coin Row (0) | 2024.07.06 |