https://www.acmicpc.net/problem/11660
11660번: 구간 합 구하기 5
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네
www.acmicpc.net
코드설명
2차원 배열의 누적합 문제입니다.
누적합을 사용할경우,
처음에 누적합 배열을 구하는데에는 O(N*N)의 시간복잡도가 주어지지만, 합을 구하는 연산이 O(1)로 줄어듭니다.
1. 누적합배열을 구하기
for(int i=1;i<=N;i++) { for(int j=1;j<=M;j++) { prefixSum[i][j] = arr[i-1][j-1] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1]; } }
- prefixSum[i][j] = 배열값 + 왼쪽 누적합 + 위쪽 누적합 - 교집합 누적합
2. 합연산 구하기
int result = prefixSum[x][y] - prefixSum[x][j-1] - prefixSum[i-1][y] + prefixSum[i-1][j-1];
- 합연산 = 전체 누적합 - 왼쪽 누적합 - 위쪽 누적합 + 교집합 누적합
문제에서 유의해야할점은.,
prefixSum[N][N]은 arr[N-1][N-1] 까지의 합을 의미한다는 점입니다.
다른말로는, 누적합배열에 있어서 prefixSum[N][M] 이라고 가정할때, prefixSum[N][M]은 arr[0][0] ~ arr[N-1][M-1] 까지의 합이라는것을 인지해야합니다.
즉, 인덱스가 1칸씩 큰 값이 prefixSum으로 주어집니다.
이는 prefixSum을 구할때 범위문제가 발생하지 않게하는데 도움이 됩니다.
예로들어, prefixSum[2][1] 이라함은, arr[0][0] ~ arr[1][0] 까지의 합을 나타냅니다.
prefixSum[1][1] 이라면, arr[0][0] ~ arr[0][0] 까지의 합이 될 것 입니다.
코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int N, M, K; public static int[][] arr; public static int[][] prefixSum; public static int answer = 0; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); arr = new int[N][N]; prefixSum = 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++) { arr[i][j] =Integer.parseInt(st.nextToken()); } } for(int i=1;i<=N;i++) { for(int j=1;j<=N;j++) { prefixSum[i][j] = arr[i-1][j-1] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1]; } } 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()); System.out.println(prefixSum[x2][y2] - prefixSum[x2][y1 - 1] - prefixSum[x1-1][y2] + prefixSum[x1-1][y1-1]); } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int N, M; public static int[][] arr; public static int[][] prefixSum; public static int sumValue = 0; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); arr = new int[N][N]; prefixSum = 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++) { arr[i][j] = Integer.parseInt(st.nextToken()); } } for(int i=1;i<N+1;i++) { for(int j=1;j<N+1;j++) { prefixSum[i][j] = arr[i-1][j-1] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1]; // System.out.print(" "+prefixSum[i][j]); } // System.out.println(); } 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()); int result = prefixSum[x2][y2] - prefixSum[x2][y1-1] - prefixSum[x1-1][y2] + prefixSum[x1-1][y1-1]; System.out.println(result); } } }
'알고리즘 > Prefix_Sum' 카테고리의 다른 글
[백준] 10986 나머지 합- 누적합(Prefix Sum) + 수학(나머지) JAVA (0) | 2023.08.13 |
---|---|
[백준] 1806 부분합 - 누적합(Prefix Sum) + 투포인터(Two Poitner) JAVA (0) | 2023.08.11 |
[백준] 21921 블로그 - 누적합(Prefix Sum) + 슬라이딩 윈도우(Sliding Window) JAVA (0) | 2023.08.06 |
[백준] 2167 2차원 배열의 합 - 2차원 누적합(Prefix Sum) JAVA (0) | 2023.07.24 |
[백준] 14929 귀찮아 (SIB) - 누적합(Prefix Sum) JAVA (0) | 2023.07.24 |