https://www.acmicpc.net/problem/11658
문제
N×N개의 수가 N×N 크기의 표에 채워져 있다. 그런데 중간에 수의 변경이 빈번히 일어나고 그 중간에 어떤 부분의 합을 구하려 한다. 표의 i행 j열은 (i, j)로 나타낸다. ($x_1$, $y_1$)부터 ($x_2$, $y_2$)까지 합이란 $x_1$ ≤ x ≤ $x_2$, $y_1$ ≤ y ≤ $y_2$를 만족하는 모든 (x, y)에 있는 수의 합이다.
예를 들어, N = 4이고, 표가 아래와 같이 채워져 있는 경우를 살펴보자.
여기서 (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, $x_1$, $y_1$, $x_2$, $y_2$가 주어진다. w = 0인 경우는 (x, y)를 c (1 ≤ c ≤ 1,000)로 바꾸는 연산이고, w = 1인 경우는 ($x_1$, $y_1$)부터 ($x_2$, $y_2$)의 합을 구해 출력하는 연산이다. (1 ≤ $x_1$ ≤ $x_2$ ≤ N, 1 ≤ $y_1$ ≤ $y_2$ ≤ 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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[][] fenwick_tree;
private static void update(int row, int idx, int value1, int value2) {
while(idx <= N) {
fenwick_tree[row][idx] = fenwick_tree[row][idx] - value1 + value2;
idx += idx & -idx;
}
}
private static int sum(int x1, int y1, int x2, int y2) {
int r = 0;
for (int i = x1; i <= x2; i++) {
int idx1 = y1 - 1;
int idx2 = y2;
// 1 ~ y2 누적합 구하기
int tmp2 = 0;
while(idx2 > 0) {
tmp2 += fenwick_tree[i][idx2];
idx2 -= idx2 & -idx2;
}
// 1 ~ y1 누적합 구하기
int tmp1 = 0;
while(idx1 > 0) {
tmp1 += fenwick_tree[i][idx1];
idx1 -= idx1 & - idx1;
}
r += tmp2 - tmp1;
}
return r;
}
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[][] arr = new int[N + 1][N + 1];
fenwick_tree = 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++) {
arr[i][j] = Integer.parseInt(st.nextToken());
update(i, j, 0, arr[i][j]);
}
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int w = Integer.parseInt(st.nextToken());
if(w == 0) {
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
update(x, y, arr[x][y], c);
arr[x][y] = c;
}
else if(w == 1) {
int x1 = Integer.parseInt(st.nextToken());
int y1 = Integer.parseInt(st.nextToken());
int x2 = Integer.parseInt(st.nextToken());
int y2 = Integer.parseInt(st.nextToken());
sb.append(sum(x1, y1, x2, y2) + "\n");
}
}
System.out.println(sb);
}
}
'Problem Solving > BOJ' 카테고리의 다른 글
[백준, BOJ 17404] RGB거리 2 (java) (0) | 2023.04.11 |
---|---|
[백준, BOJ 2636] 치즈 (java) (2) | 2023.04.11 |
[백준, BOJ 1629] 곱셈 (java) (0) | 2023.04.09 |
[백준, BOJ 1647] 도시 분할 계획 (java) (0) | 2023.04.09 |
[백준, BOJ 11659] 구간 합 구하기 4 (java) (0) | 2023.04.09 |