※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1999번 문제인 최대최소이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1999
어떤 직사각형 영역에 특정 수가 포함되어있는지 여부를 구할 수 있는 방법은 무엇이 있을까? 여기에서는 해당 수가 포함되어 있는 칸에는 1, 그렇지 않은 칸에는 0을 채운 후 2D Prefix Sum을 준비해두는 방법을 생각해보자. 이 때, 직사각형 영역의 수의 합이 0이라면 특정 수가 없는 것이고 그렇지 않다면 특정 수가 있는 것이다.
0부터 250까지의 각각의 수에 대하여 위와 같은 2D prefix sum table을 준비해두고, 각 영역에 대하여 251가지 수에 대해 해당 수가 존재하는지 확인해 문제가 요구하는 값을 구하자. 그 중 최댓값과 최솟값을 구해 출력하는 것으로 문제를 해결할 수 있다.
여담으로, 이 문제는 답을 구해야 하는 영역의 크기가 고정되어 있다는 점을 이용하면 더욱 빠른 풀이를 얻을 수 있다. 그 방법은 deque range minimum(maximum) trick을 행방향과 열방향으로 한번씩 적용하는 것이다. 이 방식의 시간복잡도는 \(O(N^2)\)이다.
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
int N, K, Q;
int A[251][251][251];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> K >> Q;
for (int r = 1; r <= N; r++) {
for (int c = 1; c <= N; c++) {
int x; cin >> x;
A[x][r][c] = 1;
}
}
for (int k = 0; k < 251; k++) {
for (int r = 1; r <= N; r++) {
for (int c = 1; c <= N; c++) {
A[k][r][c] += A[k][r - 1][c] + A[k][r][c - 1] - A[k][r - 1][c - 1];
}
}
}
while (Q--) {
int r, c; cin >> r >> c;
int mn = 1000000007, mx = -1;
for (int k = 0; k < 251; k++) {
if (A[k][r + K - 1][c + K - 1] - A[k][r - 1][c + K - 1] - A[k][r + K - 1][c - 1] + A[k][r - 1][c - 1]) {
mn = min(mn, k), mx = max(mx, k);
}
}
cout << mx - mn << '\n';
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 13733 // C++] Square Deal (0) | 2024.08.26 |
---|---|
[BOJ 17797 // C++] Dome Construction (0) | 2024.08.25 |
[BOJ 3165 // C++] 5 (0) | 2024.08.23 |
[BOJ 10379 // C++] Hiking in the Hills (0) | 2024.08.22 |
[BOJ 12111 // C++] Turnir (0) | 2024.08.21 |