-
[백준] 11660. 구간 합 구하기 5PS/Java 2022. 9. 20.
N×N개의 수가 N×N 크기의 표에 채워져 있다. (x1, y1)부터 (x2, y2)까지 합을 구하는 프로그램을 작성하시오. (x, y)는 x행 y열을 의미한다.
예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자.
여기서 (2, 2)부터 (3, 4)까지 합을 구하면 3+4+5+4+5+6 = 27이고, (4, 4)부터 (4, 4)까지 합을 구하면 7이다.
표에 채워져 있는 수와 합을 구하는 연산이 주어졌을 때, 이를 처리하는 프로그램을 작성하시오.
입력
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네 개의 정수 x1, y1, x2, y2 가 주어지며, (x1, y1)부터 (x2, y2)의 합을 구해 출력해야 한다. 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수이다. (x1 ≤ x2, y1 ≤ y2)
출력
총 M줄에 걸쳐 (x1, y1)부터 (x2, y2)까지 합을 구해 출력한다.
예제 입력 1
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
예제 출력 1
27 6 64
누적 합 배열을 만들 때 인덱스 접근을 편하게 하기 위해 위/왼쪽으로 한칸씩 더 추가해준다.
예를 들어 (0, 0)부터 (3, 2)까지의 합을 구할땐
(0, 0)부터 (3, 2 - 1)까지의 합(주황색 부분), (0, 0)부터 (2, 2)까지의 합(초록색 부분)을 더한 후 (3, 2)의 값을 더한 다음 2번 더해져서 중복되는 부분인 (0, 0)부터 (2, 1)인 부분을 빼 주면 해당 부분의 누적합이 된다.
해당 부분에선 x가 0 또는 y가 0일때의 값은 전부 0이기 때문에 다음에 구할 배열에서는 시작 좌표는 항상 (1, 1) 부터이다.
누적 합 배열을 만들고 (x1, y1)부터 (x2, y2)까지의 합을 구할 땐 위와 비슷한 방법으로 (1, 1)부터 (x2, y2) 까지의 합을 구한 후 (1, 1)부터 (x2, y1 - 1)를 빼고 (1, 1)부터 (x1 - 1, y2)를 빼고 두번 빼서 중복되는 부분인 (1, 1)부터 (x1 - 1, y1 - 1)을 더해주면 된다.
하지만 우리는 이미 누적 합 배열을 만들어 놓았기 때문에 좌표를 직접 계산해 줄 필요는 없고 바로 누적합 배열에서 접근하여 계산만 해주면 된다.
arr[x2][y2] - arr[x2][y1 - 1] - arr[x1 - 1][y2] + arr[x1 - 1][y1- 1]
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.StringTokenizer; public class Main11660 { public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); public static int N, M; public static int[][] arr; public static void main(String[] args) throws Exception { StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); arr = new int[N + 1][N + 1]; for(int i = 0; i < N; i++) { st = new StringTokenizer(br.readLine()); for(int j = 0; j < N; j++) { int next = Integer.parseInt(st.nextToken()); arr[i + 1][j + 1] = arr[i][j + 1] + arr[i + 1][j] - arr[i][j] + next; } } for(int i = 0; i < M; i++) { st = new StringTokenizer(br.readLine()); // (1, 1, x2, y2)에서 // (1, 1, x2, y1 - 1) 빼기 // (1, 1, x1 - 1, y2) 빼기 // (1, 1, x1 - 1, y1 - 1) 한번 더하기 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 = arr[x2][y2] - arr[x2][y1 - 1] - arr[x1 - 1][y2] + arr[x1 - 1][y1- 1]; bw.write(res + "\n"); } br.close(); bw.flush(); bw.close(); } }
'PS > Java' 카테고리의 다른 글
[백준] 11404. 플로이드 (1) 2022.09.20 [백준] 11725. 트리의 부모 찾기 (1) 2022.09.20 [백준] 13549. 숨바꼭질 3 (0) 2022.07.19 [백준] 15654. N과 M (5) (0) 2022.07.19 [백준] 1865. 웜홀 (0) 2022.07.19