문제
https://www.acmicpc.net/problem/11505
풀이(25분)
import java.io.*;
import java.util.*;
public class Main {
static int n, m, k, squareNum;
static long[] segmentTree;
static final int MOD = 1_000_000_007;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken()); // 숫자 개수
m = Integer.parseInt(st.nextToken()); // 바꾸는 횟수
k = Integer.parseInt(st.nextToken()); // 구간 곱 구하는 횟수
int height = 0;
while (Math.pow(2, height) < n) height++;
squareNum = (int) Math.pow(2, height);
segmentTree = new long[squareNum * 2];
Arrays.fill(segmentTree, 1);
// 리프에 값 채우기
for (int i = squareNum; i < squareNum + n; i++) {
segmentTree[i] = Long.parseLong(br.readLine());
}
// 부모 노드 채우기
for (int i = squareNum - 1; i > 0; i--) {
segmentTree[i] = (segmentTree[i * 2] * segmentTree[i * 2 + 1]) % MOD;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < m + k; i++) {
st = new StringTokenizer(br.readLine());
int op = Integer.parseInt(st.nextToken());
if (op == 1) {
int idx = Integer.parseInt(st.nextToken());
long value = Long.parseLong(st.nextToken());
update(idx, value);
} else {
int left = Integer.parseInt(st.nextToken());
int right = Integer.parseInt(st.nextToken());
sb.append(query(left, right)).append("\n");
}
}
System.out.print(sb);
}
static void update(int idx, long value) {
int node = squareNum + idx - 1;
segmentTree[node] = value;
node /= 2;
while (node > 0) {
segmentTree[node] = (segmentTree[node * 2] * segmentTree[node * 2 + 1]) % MOD;
node /= 2;
}
}
static long query(int left, int right) {
left += squareNum - 1;
right += squareNum - 1;
long result = 1;
while (left <= right) {
if (left % 2 == 1) result = (result * segmentTree[left++]) % MOD;
if (right % 2 == 0) result = (result * segmentTree[right--]) % MOD;
left /= 2;
right /= 2;
}
return result;
}
}
문제 풀이 전략
구간 곱을 구하기 위해 세그먼트 트리를 사용하였다. 구간 곱 자체는 곱배열(구간합과 비슷한)을 사용하는 것이 좋을 수 있지만, 업데이트가 발생한다는 특성을 해결하기 위해 세그먼트 트리를 사용한 것이다.
만약 세그먼트 트리를 모른다면 아래 링크를 참고해서 개념과 문제를 익혀보도록 하자!
[도구정리] 세그먼트 트리(Segment Tree) 알고리즘
진행하는 과정에서 생길 수 있는 부분에 대해서는 Q.라고 적어두고 하단부에 모두 설명할 테니 참고하자. 개념주어진 데이터의 구간 합과 데이터 업데이트를 빠르게 수행하기 위해 고안해낸 자
to-travel-coding.tistory.com
[백준] 2042번. 구간 합 구하기(JAVA)
문제https://www.acmicpc.net/problem/2042풀이(30분)import java.io.*;import java.util.*;public class Main { static long[] segmentTree; static int squareNum; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedRead
to-travel-coding.tistory.com
'문제 풀이 > 백준' 카테고리의 다른 글
[백준] 14428번. 수열과 쿼리 16(JAVA) (0) | 2025.04.14 |
---|---|
[백준] 2357번. 최솟값과 최댓값(JAVA) (0) | 2025.04.13 |
[백준] 2042번. 구간 합 구하기(JAVA) (0) | 2025.04.13 |
[백준] 1019번. 책 페이지(JAVA) (0) | 2025.04.11 |
[백준] 16565번. N포커(JAVA) (0) | 2025.04.11 |