[java] 백준(BOJ) - 구간합구하기

2 분 소요

업데이트:

문제

백준-구간합구하기
요청에 따라 원소를 교체하거나 구간의 합을 구하는 문제

풀이

세그먼트 트리 개념을 익힌 만큼 적용 겸 푸는 문제
완전 정석대로여서 초기 입력, 값 업데이트, 구간 구하기가 들어있다

다만 타입을 long으로 잡아줘야한다

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class b2042_구간합구하기 {

	private static int K;
	private static int M;
	private static int N;
	static long[] arr;
	static long[] nums;

	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());
		K = Integer.parseInt(st.nextToken());

		StringBuilder sb = new StringBuilder();
		// 세그먼트 트리 크기
		long H = (long) (Math.ceil(Math.log(N) / Math.log(2)));
		long size = (long) Math.pow(2, H + 1);
		arr = new long[(int) size];
		nums = new long[N];
		for (int i = 0; i < N; i++) {
			nums[i] = Long.parseLong(br.readLine());
		}

		init(1, 0, N - 1);
		for (int i = 0; i < M + K; i++) {
			st = new StringTokenizer(br.readLine());
			if (st.nextToken().equals("1")) { // b를 c로 교체
				int b = Integer.parseInt(st.nextToken());
				long diff = nums[b - 1] * -1;
				long newVal = Long.parseLong(st.nextToken());
				diff = diff + newVal;
				update(1, 0, N - 1, b - 1, diff);
			} else { // b부터 c까지 합
				int b = Integer.parseInt(st.nextToken());
				int c = Integer.parseInt(st.nextToken());
				sb.append(sum(1, 0, N - 1, b - 1, c - 1));
				sb.append("\n");
			}
		}
		System.out.println(sb.toString());
	}

	private static long init(int node, int start, int end) {
		if (start == end) {
			arr[node] = nums[start];
			return arr[node];
		}
		int mid = (start + end) / 2;
		return arr[node] = init(node * 2, start, mid) + init(node * 2 + 1, mid + 1, end);
	}

	private static long sum(int node, int start, int end, int left, int right) {
		if (end < left || right < start)
			return 0;
		if (left <= start && end <= right)
			return arr[node];
		int mid = (start + end) / 2;
		return sum(node * 2, start, mid, left, right) + sum(node * 2 + 1, mid + 1, end, left, right);
	}

	private static void update(int node, int start, int end, int idx, long diff) {
		if (start == end && idx == start)
			nums[idx] += diff;

		if (idx > end || idx < start)
			return;
		arr[node] += diff;
		if (start != end) {
			int mid = (start + end) / 2;
			update(node * 2, start, mid, idx, diff);
			update(node * 2 + 1, mid + 1, end, idx, diff);
		}
	}
}

태그:

카테고리:

업데이트:

댓글남기기