포스트

(백준/C++) 11660_구간 합 구하기 5

11660번: 구간 합 구하기 5 (acmicpc.net) 문제는 2차원 배열에서 누적 합을 통해 특정 구간의 합을 빠르게 계산하기 위한 방법을 묻는 문제입니다.

누적 합 문제는 구간에 있는 수의 합을 빠르게 계산하기 위한 방법입니다.

이를 이용하면 $O(N^2)$의 시간 복잡도로 누적 합 배열을 생성하고, 특정 구간의 합을 $O(1)$의 시간 복잡도로 계산할 수 있습니다.


로직 설계

이 문제는 먼저 11659번: 구간 합 구하기 4 (acmicpc.net) 문제를 풀고 오는 것을 추천 드립니다.

이 문제는 $(x1, y1)$부터 $(x2, y2)$까지 합을 구하는 문제입니다.

(백준/C++) 11659_구간 합 구하기 4 풀이 글

1차원 구간 합의 개념

2차원 구간 합을 구하기 전에 먼저 구간 합을 구하는 방법부터 보겠습니다.

(3~4) 구간은 (1~4) 구간에서 (1~2) 구간을 빼는 것으로 구할 수 있습니다.

구간합1

따라서, 만약 수를 누적 해 저장한다고 한다면, 두 누적 합의 계산만으로 구간 합을 쉽게 구할 수 있게 됩니다.

2차원 구간 합의 개념

위 개념을 응용한다면, 2차원 구간 합을 구하는 방법도 어렵지 않게 생각할 수 있습니다.

예를 들어, (2, 2)부터 (3, 4)까지 합을 구하기 위해서는 (3, 4)까지 합에서 (3, 1)까지의 합과 (1, 4)까지의 합을 빼는 것으로 구할 수 있습니다.

구간합5


풀이

누적 합을 저장할 때, 저는 바로 위의 누적 합과 왼쪽의 누적 합을 더해서 계산 했습니다.

이때, 겹치는 구간이 존재하기 때문에 sum[i - 1][j - 1] 을 빼서 저장했습니다. 이렇게 함으로써, 중복으로 합산되는 부분을 제거할 수 있습니다.

또한, 누적 합을 계산할 때에도 마찬가지로 위쪽과 왼쪽의 누적 합을 빼는데, 겹치는 구간이 존재하기 때문에 이 부분도 sum[x1 - 1][y1 - 1] 을 더하는 것으로 계산 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;

int sum[1025][1025];

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	int N, M;
	cin >> N >> M;

	// 2차원 정수 입력 받으며 합산하기
	for (int i = 1; i <= N; i++)
	{
		for (int j = 1; j <= N; j++)
		{
			cin >> sum[i][j];
			sum[i][j] += sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
		}
	}

	//범위 계산
	while (M--)
	{
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		cout << (sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1]) << '\n';
	}
}
이 기사는 저작권자의 CC BY-NC-ND 4.0 라이센스를 따릅니다.