문제
N×N개의 수가 N×N 크기의 표에 채워져 있다. (x1, y1)부터 (x2, y2)까지 합을 구하는 프로그램을 작성하시오. (x, y)는 x행 y열을 의미한다.
예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자.
| 1 | 2 | 3 | 4 |
| 2 | 3 | 4 | 5 |
| 3 | 4 | 5 | 6 |
| 4 | 5 | 6 | 7 |
여기서 (2, 2)부터 (3, 4)까지 합을 구하면 3+4+5+4+5+6 = 27이고, (4, 4)부터 (4, 4)까지 합을 구하면 7이다.
표에 채워져 있는 수와 합을 구하는 연산이 주어졌을 때, 이를 처리하는 프로그램을 작성하시오.
- 1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000
- 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수
풀이
N의 최대 크기가 1024 x 1024 = 1,048,576이고, 이 행렬에서 구해야 하는 구간 합의 최대 횟수가 100,000이므로 브루트 포스로는 연산이 어려워 보인다.
행렬(2차원 배열)에서의 누적 합을 미리 구해두고, 이를 활용해야 한다.
행렬에서의 누적 합과 구간 합은 다음과 같이 구할 수 있다.

그림의 누적 합 구하는 과정을 일반화하면 아래와 같다.
prefixSum[i][j] =
matrix[i][j]
+ prefixSum[i-1][j]
+ prefixSum[i][j-1]
- prefixSum[i-1][j-1]
구간 합은 다음과 같이 구할 수 있다.
rangeSum = prefixSum[x2][y2]
- prefixSum[x1 - 1][y2]
- prefixSum[x2][y1 - 1]
+ prefixSum[x1 - 1][y1 - 1];
코드
const input = require("fs")
.readFileSync(process.platform === "linux" ? 0 : "./input.txt", "utf8")
.trim()
.split("\n");
const [n, m] = input[0].split(" ").map(Number);
const grid = Array.from({ length: n + 1 }, (_, i) =>
i === 0 ? Array(n + 1).fill(0) : [0, ...input[i].split(" ").map(Number)]
);
const points = input
.slice(n + 1, n + 1 + m)
.map(line => line.split(" ").map(Number))
const prefix = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= n; j++) {
prefix[i][j] =
grid[i][j]
+ prefix[i - 1][j]
+ prefix[i][j - 1]
- prefix[i - 1][j - 1];
}
}
const sum = (x1, y1, x2, y2) =>
prefix[x2][y2]
- prefix[x1 - 1][y2]
- prefix[x2][y1 - 1]
+ prefix[x1 - 1][y1 - 1];
for (const [x1, y1, x2, y2] of points) {
console.log(sum(x1, y1, x2, y2));
}'Problem Solving > BOJ' 카테고리의 다른 글
| [BOJ/JavaScript] 15686: 치킨 배달 (1) | 2025.07.24 |
|---|---|
| [BOJ/JavaScript] 1987: 알파벳 (5) | 2025.07.22 |
| [BOJ/JavaScript] 9328: 열쇠 (1) | 2025.06.30 |
| [BOJ/JavaScript] 1541: 잃어버린 괄호 (1) | 2025.06.21 |
| [BOJ/JavaScript] 7453: 합이 0인 네 정수 (0) | 2025.06.17 |