Algorithm/Problem Solving
[BOJ] 11660. 구간 합 구하기5 - JAVA 자바 ✨누적합✨
gangintheremark
2024. 2. 18. 12:56
728x90
11660번: 구간 합 구하기 5
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네
www.acmicpc.net
- 누적합
2차원 배열에 대해 누적합을 저장하는 경우 O(N*N)의 시간 복잡도가 주어지지만, 합을 구하는 연산이 O(1)로 줄어든다. prefixSum[a][b] 를 (1,1)부터 (a,b) 까지의 합이라고 하자
왼쪽이 주어진 배열이고 오른쪽이 누적합을 저장한 이차원 배열이다.
(1,1)에서 (2,3)까지의 누적합을 구하고자 하면 왼쪽 누적합과 위쪽 누적합을 더한 값에 교집합으로 두 번 더해지는 구간을 한 번 빼준 후 (2,3)의 배열값을 더해주면 쉽게 구할 수 있다.
prefixSum[2][3] = arr[2][3] + prefixSum[2][2] + prefixSum[1][3] - prefixSum[1][2]
따라서 다음과 같은 식을 세울 수 있다.
prefixSum[i][j] = arr[i][j] + prefixSum[i][j-1] + prefixSum[i-1][j] - prefixSum[i-1][j-1]
주의할 점은 누적합 배열 prefixSum[N][N]은 DP Bottom-Up 방식으로 인덱스가 1칸씩 큰 값으로 선언해주야 한다.
👩🏻💻 소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int[][] prefixSum = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 1; j <= n; j++) {
prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1]
+ Integer.parseInt(st.nextToken());
}
}
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine(), " ");
int x1 = Integer.parseInt(st.nextToken());
int y1 = Integer.parseInt(st.nextToken());
int x2 = Integer.parseInt(st.nextToken());
int y2 = Integer.parseInt(st.nextToken());
int res = prefixSum[x2][y2] - prefixSum[x1 - 1][y2] - prefixSum[x2][y1 - 1] + prefixSum[x1 - 1][y1 - 1];
sb.append(res).append('\n');
}
System.out.println(sb);
}
}
728x90