문제
https://www.acmicpc.net/problem/11660
소스코드
import sys
input = sys.stdin.readline
if __name__ == "__main__":
n,m = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(n)]
dp = [[0] * (n+1) for _ in range(n+1)]
for i in range(1,n+1):
for j in range(1,n+1):
dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + arr[i-1][j-1]
for k in range(m):
x1,y1,x2,y2 = list(map(int,input().split()))
print(dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1])
설명
1 | 2 | 3 |
2 | 3 | 4 |
3 | 4 | 5 |
(1,1) 부터 (2,3) 까지 합을 구하라면 (3+4+4+5) 을 더한 값이 최종 결과가 된다.
단순 반복문을 이용해서도 풀 수 있지만 시간초과 오류가 발생한다.
이런 문제는 구간 합으로 해결하면 된다.
prefix sum (구간 합)
구간 합은 어떤 수열에서 해당 인덱스까지 수열의 전체 합을 의미한다.
예를 들어 [10,20,30,40,50]의 구간합은 [10, 10+20, 10+20+30, 10+20+30+40,10+20+30+40+50] 으로 누적된 값이다.
이제 위의 2차원 배열을 구간 합을 이용해서 나타내면 아래와 같다.
1 | 1+2 | 1+2+3 |
1+2 | 1+2+2+3 | 1+2+2+3+3+4 |
1+2+3 | 1+2+2+2+3+3+4 | 1+2+2+3+3+3+4+4+5 |
위의 누적합에서 (2,2) ~ (3,3) 의 누적합을 구하려고 한다면 : 빨간색 섹션
전체 누적합에서 ((3,3) 의 값) 초록색 영역을 제거해준다 (1,3) 과 (3,1)
그리고 초록색 중에 (1,1) 은 중복으로 제거됬으므로 한번 추가해준다.
그래서 최종 코드는 dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dx[x1-1][y1-1] 이 우리가 원하는 값이 된다.
'Algorithm' 카테고리의 다른 글
[백준][python]20055 컨베이어 벨트 위의 로봇 (0) | 2023.07.24 |
---|---|
[백준][python]9935 문자열 폭팔 (0) | 2023.07.13 |
[백준][python]1159 농구경기 (0) | 2023.07.05 |
[백준][python]1958 LCS3 (0) | 2023.07.05 |
[백준][python]13460 구슬탈출2 (0) | 2023.06.28 |