Baekjoon Review
[Silver 1] 11660번 구간 합 구하기 5
hanseongbugi
2023. 11. 8. 18:58
https://www.acmicpc.net/problem/11660
11660번: 구간 합 구하기 5
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네
www.acmicpc.net
이 문제는 DP를 통한 누적합을 구하는 문제이다.
DP를 통해 누적합을 구하기 위해서 아래 식을 사용한다.
누적합(X, Y) = 누적합(X-1, Y) + 누적합(X, Y-1) - 누적합(X-1, Y-1) + 요소(X, Y)
- 누적합 (X-1, Y-1)을 빼는 이유는 누적합 (X-1, Y) + (X, Y-1)에서 (X-1, Y-1)이 공통으로 들어가 한번만 합하기 위해 사용
누적합을 모두 구하였다면 부분합을 구해야한다.
부분합을 구하기 위해 아래 식을 사용한다.
부분합 = 누적합(X2, Y2) - 누적합(x2,y1 - 1) - 누적합(x1 - 1,y2) + 누적합(x1 - 1,y1 - 1)
- X2와 Y2까지의 부분합을 구하기 위해서는 X2, Y2까지의 누적합을 이용한다.
- 이때 필요하지 않는 구간을 빼야한다.
- 즉, (X2, Y1-1)과 (X1 - 1, Y2)구간까지의 누적 합을 빼주고, 겹치는 구간인 (X1 - 1, Y1 - 1)을 합한다. (2번 빼줬기 때문)
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 1025; // 최대 배열 크기
int N, M;
int arr[MAXN][MAXN] = {0, };
int dp[MAXN][MAXN] = {0, };
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++)
cin >> arr[i][j];
}
// 누적 합 계산
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + arr[i][j];
}
}
for (int i = 0; i < M; i++) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
// 부분 합 계산
int result = dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1];
cout << result << '\n';
}
return 0;
}