[Python] 백준 #11658 구간 합 구하기 3

이재원·2023년 9월 11일

Algorithm

목록 보기
4/29

📚문제: #11658 구간 합 구하기 3(Platinum 4)

N×N개의 수가 N×N 크기의 표에 채워져 있다. 그런데 중간에 수의 변경이 빈번히 일어나고 그 중간에 어떤 부분의 합을 구하려 한다. 표의 i행 j열은 (i, j)로 나타낸다. (x1, y1)부터 (x2, y2)까지 합이란 x1 ≤ x ≤ x2, y1 ≤ y ≤ y2를 만족하는 모든 (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이 된다. (2, 3)을 7로 바꾸고 (2, 2)부터 (3, 4)까지 합을 구하면 3+7+5+4+5+6=30 이 된다.

표에 채워져 있는 수와 변경하는 연산과 합을 구하는 연산이 주어졌을 때, 이를 처리하는 프로그램을 작성하시오.

입력

첫째 줄에 표의 크기 N과 수행해야 하는 연산의 수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네 개의 정수 w, x, y, c 또는 다섯 개의 정수 w, x1, y1, x2, y2가 주어진다. w = 0인 경우는 (x, y)를 c (1 ≤ c ≤ 1,000)로 바꾸는 연산이고, w = 1인 경우는 (x1, y1)부터 (x2, y2)의 합을 구해 출력하는 연산이다. (1 ≤ x1 ≤ x2 ≤ N, 1 ≤ y1 ≤ y2 ≤ N) 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수이다.

출력

w = 1인 입력마다 구한 합을 순서대로 한 줄에 하나씩 출력한다.

예제 입력 1

4 5
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
1 2 2 3 4
0 2 3 7
1 2 2 3 4
0 3 4 5
1 3 4 3 4

예제 출력 1

27
30
5

아이디어 및 구현

  • 시간 초과를 방지하기 위해 누적 합 개념을 적용하여 알고리즘을 작성한다.
# 구간 합 계산을 위해 표의 원본을 복사
array_sum = deepcopy(array)

# 구간 합 계산
# array_sum[i][j]는 array의 i행 0열 ~ i행 j열 까지 모든 수의 합
for i in range(N):

    for j in range(1, N):

        array_sum[i][j] += array_sum[i][j-1]
  • 표의 숫자가 바뀌는 상황을 고려한다.
    1. array의 숫자를 변경한다. 변경되는 숫자를 c라고 하자.
    2. c와 원래 숫자의 차이만큼 누적 합 리스트인 array_sum에 반영한다.
# 입력 받은 숫자의 길이가 4일 때
w, x, y, c = temp

x -= 1
y -= 1

# 변경되는 숫자와 원래 숫자의 차이
diff = c - array[x][y]

# 숫자 변경 반영
array[x][y] = c

# 누적합 리스트의 x행 y열 ~ x행 N-1열 값에 차이만큼 다 더해준다.
for i in range(y,N):

    array_sum[x][i] += diff

전체 코드

import sys
from copy import deepcopy

# N, M이 주어집니다.
N, M = map(int, sys.stdin.readline().split())

# 표 초기화
array = []

# 표에 입력할 수가 주어집니다.
for _ in range(N):

    array.append(list(map(int, sys.stdin.readline().split())))

# 구간 합 계산을 위한 표 복사
array_sum = deepcopy(array)

# 구간 합 계산
for i in range(N):

    for j in range(1, N):

        array_sum[i][j] += array_sum[i][j-1]

# 정수가 주어집니다.
for _ in range(M):

    temp = list(map(int, sys.stdin.readline().split()))
	
    # 입력 길이가 5일 때, 누적합 계산 
    if len(temp) == 5:

        w, x1, y1, x2, y2 = temp

        x1 -= 1
        y1 -= 1
        x2 -= 1
        y2 -= 1

        # 누적 합
        ans = 0
		
        # x1 ~ x2행에 대하여 누적 합 계산, 최종 답을 출력할 변수에 다 더해줌
        for i in range(x1, x2+1):

            if y1 == 0:
                
                ans += array_sum[i][y2]
            
            else: # y1 != 0
                
                ans += (array_sum[i][y2]-array_sum[i][y1-1])
        
        print(ans)
        
    # 입력 길이가 4일 때, 표와 누적 합 리스트 변경
    else: # len(temp) == 4

        w, x, y, c = temp

        x -= 1
        y -= 1
		
        # 변경되는 숫자와 원래 숫자의 차이 계산
        diff = c - array[x][y]
		
        # 숫자 변경
        array[x][y] = c
		
        # 누적 합 리스트 변경(차이만큼 더해줌)
        for i in range(y,N):

            array_sum[x][i] += diff

0개의 댓글