(1 <= N <= 1024), (1 <= M <= 100,000)
배열을 채우기 위해 N * N개의 칸을 모두 한 번씩 방문 하기때문에 -> O(N^2)
누적합 배열을 이용해서 4번만 더하고 빼면 되기 때문에 -> O(M)
💡 O(N^2 + M) 이 시간 복잡도
최악의 경우 : 1024 * 1024 + 100,000 약 110만 번 계산이면 될 것 같다..
예제 입력 2,2,3,4를 보고 함께 풀어보자 - 사진은 원본 배열 A[i][j]
임
우리가 구해야하는 것은 노란색 박스이다
그전에 구간 합 배열을 채워야지 노란색 박스의 구간 합을 구할 수 있다
D[i][j] = D[i][j-1] + D[i-1][j] - D[i-1][j-1] + A[i][j]
위 공식을 가지고 구간 합 배열을 완성 시켜주면 사진이 나온다
노란색 박스의 구간 합을 구하려면
녹색 박스 - 파란색 박스 - 빨간색 박스 + 보라색 박스를 구하면 된다
D[3][4] - D[3][1] - D[1][4] + D[1][1]
= 노란색 박스 가 나오게 된다D[x2][y2] - D[x2][y1 - 1] - D[x1 - 1][y2] + D[x1 - 1][y1 - 1]
1. N * N (배열 크기), M (질의 수) 저장
2. for(N만큼 반복) {
2-1. for(N만큼 반복) {
2-2. 원본 배열 저장
}
}
3. for(N만큼 반복) {
3-1. for(N만큼 반복) {
3-2. 구간 합 배열 저장
}
}
4. for(M만큼 반복) {
4-1. 질의 숫자 저장
4-2. 구간 합 배열 결과 저장 및 출력
}
package dataSource;
import java.io.*;
import java.util.StringTokenizer;
public class No_11660 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int A[][] = new int[N+1][N+1];
for(int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
for(int j = 1; j <= N; j++) {
A[i][j] = Integer.parseInt(st.nextToken());
}
}
int D[][] = new int[N+1][N+1];
for(int i = 1; i<=N; i++ ) {
for(int j = 1; j<=N; j++) {
D[i][j] = D[i][j-1] + D[i-1][j] - D[i-1][j-1] + A[i][j];
}
}
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 = D[x2][y2] - D[x2][y1 - 1] - D[x1 - 1][y2] + D[x1 - 1][y1 - 1];
System.out.println(result);
}
}
}