본문 바로가기

BAEKJOON/다이나믹 프로그래밍

백준 11660번 [구간 합 구하기 5](C++)-yes6686- 티스토리

728x90
SMALL

백준 문제 풀이: 11660 [구간 합 구하기 5]


문제 링크: https://www.acmicpc.net/problem/11660

문제 설명:

2차원 배열에서 특정 구간의 합을 구하는 문제입니다. 입력된 행렬에서 여러 쿼리에 대해 지정된 좌표 범위의 합을 효율적으로 계산해야 합니다.

입력:

  • 첫째 줄에 정수 nm이 주어집니다. (1 ≤ n ≤ 1,024, 1 ≤ m ≤ 100,000)
  • 다음 n개의 줄에는 행렬의 원소가 주어집니다. 행렬의 원소는 1,000 이하의 자연수입니다.
  • 이후 m개의 줄에는 네 개의 정수 x1, y1, x2, y2가 주어집니다.

출력:

  • 각 쿼리에 대해 지정된 좌표 구간의 합을 한 줄에 하나씩 출력합니다.

문제 해결 코드


#include <iostream>
using namespace std;

int arr[1025][1025];
int prefixSum[1025][1025];

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

    int n, m;
    cin >> n >> m;

    // 입력받고 누적합 계산
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> arr[i][j];
            prefixSum[i][j] = arr[i][j] + prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1];
        }
    }

    // 쿼리 처리
    for (int i = 0; i < m; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;

        int sum = prefixSum[x2][y2]
                  - prefixSum[x1 - 1][y2]
                  - prefixSum[x2][y1 - 1]
                  + prefixSum[x1 - 1][y1 - 1];

        cout << sum << '\n';
    }

    return 0;
}

예제

입력:
4 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
2 2 3 4
3 4 3 4
1 1 4 4

출력:
27
6
64

코드 설명

  • 누적합 계산:
    • prefixSum[i][j]는 (1,1)부터 (i,j)까지의 합을 저장합니다.
    • 이를 통해 특정 구간의 합을 O(1)에 계산할 수 있습니다.
  • 구간 합 계산:
    • 주어진 좌표 범위에서 누적합을 사용해 결과를 구합니다:
    • prefixSum[x2][y2]: 구간의 전체 합
    • - prefixSum[x1-1][y2]: 제외할 위쪽 영역
    • - prefixSum[x2][y1-1]: 제외할 왼쪽 영역
    • + prefixSum[x1-1][y1-1]: 제외된 영역의 중복 보정

시간 복잡도

  • 누적합 계산: O(n²)
  • 각 쿼리 처리: O(1)
  • 전체 시간 복잡도: O(n² + m)

결과

코드는 2차원 배열에서의 구간 합 문제를 효율적으로 해결하며, 누적합 기법을 통해 O(1)로 쿼리를 처리할 수 있습니다. 입력 크기가 최대 1024×1024이므로 문제의 제약을 만족하는 성능을 보장합니다.

다른 접근 방식이나 개선 사항이 있다면 댓글로 공유 부탁드립니다!

728x90
LIST