※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 14846번 문제인 직사각형과 쿼리이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/14846

 

14846번: 직사각형과 쿼리

첫째 줄에 N (1 ≤ N ≤ 300)이 주어진다. 다음 N개의 줄에는 행렬의 정보가 주어지며, 각 줄은 N개의 수로 이루어져 있다. 행은 위에서부터 아래로, 열은 왼쪽부터 오른쪽으로 번호가 매겨져 있으며

www.acmicpc.net

주어지는 행렬의 원소의 원소로 가능한 수의 가짓수가 10가지로 매우 적음을 눈여겨보자.

 

어떤 원소 k가 x1,y1을 좌상단 칸으로, x2,y2를 우하단 칸으로 하는 직사각형 영역에 존재한다는 것은 이 영역에 k가 양수개 존재한다는 것과 같다. 그러므로 가능한 k의 값인 1부터 10까지의 값에 대하여 영역에 포함된 k의 개수를 구하는 2차원 prefix sum 배열을 만들고, 쿼리마다 이 10개의 배열을 참조해 해당 영역에 k가 몇 개 있는지를 세어 그 개수가 양수인지를 이용해 문제를 해결할 수 있다.

 

시간복잡도는 전처리에 \(O(N^2*K)\) (단, \(K\)는 직사각형 영역에 존재하는 수의 가짓수), 쿼리 해결에 \(O(Q)\)이고 이 복잡도는 문제를 해결하기에 충분하다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;

int N, Q;
int dp[301][301][10];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N; N++;
	for (int r = 1; r < N; r++) {
		for (int c = 1; c < N; c++) {
			for (int i = 0; i < 10; i++) dp[r][c][i] = dp[r - 1][c][i] + dp[r][c - 1][i] - dp[r - 1][c - 1][i];
			int x; cin >> x;
			dp[r][c][x - 1]++;
		}
	}

	cin >> Q;
	while (Q--) {
		int ret = 0;
		int xL, xR, yL, yR; cin >> xL >> yL >> xR >> yR;
		xL--, yL--;
		for (int i = 0; i < 10; i++) {
			if (dp[xR][yR][i] - dp[xL][yR][i] - dp[xR][yL][i] + dp[xL][yL][i]) ret++;
		}

		cout << ret << '\n';
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 16174 // C++] 점프왕 쩰리 (Large)  (0) 2023.02.17
[BOJ 3186 // C++] 소변기  (0) 2023.02.17
[BOJ 3187 // C++] 양치기 꿍  (0) 2023.02.17
[BOJ 26171 // C++] An Interactive Problem  (0) 2023.02.17
[BOJ 27487 // C++] One and Two  (0) 2023.02.17

+ Recent posts