코딍코딍
코딩기록
코딍코딍
전체 방문자
오늘
어제
  • 분류 전체보기 (271)
    • 개발 (2)
    • Java (1)
    • 스프링 (28)
    • JPA (11)
    • Git (3)
    • 알고리즘 (160)
      • 백준 (132)
      • 프로그래머스 (8)
      • SWEA (20)
    • 토이 프로젝트 (14)
      • 간단한 Springboot CRUD (1)
      • 게시판 프로젝트 (13)
    • 알고리즘 개념정리 (8)
    • 오류 해결 (13)
    • 보류 (0)
    • AWS (5)
    • 트러블 슈팅 (0)
    • 회고 (3)
    • CS (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

최근 글

티스토리

hELLO · Designed By 정상우.
코딍코딍

코딩기록

알고리즘/백준

[백준] 11660번 : 구간 합 구하기 5

2024. 1. 22. 21:20

https://www.acmicpc.net/problem/11660

 

11660번: 구간 합 구하기 5

첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네

www.acmicpc.net

 

문제

N×N개의 수가 N×N 크기의 표에 채워져 있다. (x1, y1)부터 (x2, y2)까지 합을 구하는 프로그램을 작성하시오. (x, y)는 x행 y열을 의미한다.


예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자.
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
여기서 (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)까지 합을 구해 출력한다.

 


소스코드

import java.util.*;
import java.io.*;

class Main {

    public static void main(String[] args) throws Exception {
        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 arr[][] = new int[n][n];
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < n; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        long sum = 0;
        long dp[][] = new long[n + 1][n + 1];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                sum += arr[i][j];
                dp[i + 1][j + 1] = sum;
            }
        }

        dp[1][0] = 0;
        for (int i = 2; i <= n; i++) {
            dp[i][0] = dp[i - 1][n];
        }

        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());

            long result = 0;
            for (int j = x1; j <= x2; j++) {
                result += (dp[j][y2] - dp[j][y1 - 1]);
            }
            sb.append(result + "\n");
        }

        System.out.println(sb);
    }
}

 

해결 방법

(2, 2)부터 (3, 4)까지 합은 (3, 2) ~ (3, 4)와 (2, 2) ~ (2, 4) 구간의 합과 동일하다.

이 구간의 합을 구하기 위해 누적합을 적용하면 쉽게 해결할 수 있다.

 

(3, 2) ~ (3, 4) 구간의 합은 (3, 4)까지의 누적합 - (3, 1)까지의 누적합과 동일하다.

(2, 2) ~ (2, 4) 구간의 합은 (2, 4)까지의 누적합 - (2, 1)까지의 누적합과 동일하다.

 

이를 식으로 표현하면
(dp[x1][y2] - dp[x1][y1-1]) + ... + (dp[x2][y2] - dp[x2][y1-1])이다.

dp[x][y]는 dp[1][1] + dp[1][2] + ... + dp[x][y]이다.

 

고로 (2, 2)부터 (3, 4)까지 합은 아래의 두 식의 합과 동일하다.

  • dp[2][4] - dp[2][1]
  • dp[3][4] - dp[3][1] 

 

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 13549번 : 숨바꼭질 3  (0) 2024.01.23
[백준] 2468번 : 안전 영역  (0) 2024.01.22
[백준] 12018번 : Yonsei TOTO  (1) 2024.01.21
[백준] 1890번 : 점프  (0) 2024.01.19
[백준] 2589번 : 보물섬  (0) 2024.01.17
    '알고리즘/백준' 카테고리의 다른 글
    • [백준] 13549번 : 숨바꼭질 3
    • [백준] 2468번 : 안전 영역
    • [백준] 12018번 : Yonsei TOTO
    • [백준] 1890번 : 점프
    코딍코딍
    코딍코딍
    ㅎ2

    티스토리툴바