ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 11660. 구간 합 구하기 5
    PS/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

    댓글

Designed by Tistory.