갓생사는 김초원의 개발 블로그
chocho_log
갓생사는 김초원의 개발 블로그
전체 방문자
오늘
어제
  • 분류 전체보기 (76)
    • 개발 (22)
      • Spring (4)
      • Java (3)
      • Database (2)
      • Elasticsearch (3)
      • ETC (3)
      • JPA (3)
      • 이슈 (1)
    • 코딩 테스트 (43)
      • 프로그래머스 (23)
      • 백준 (12)
      • TIP (8)
    • 자료구조 (2)
    • 알고리즘 (4)
    • 잡생각 (0)
    • 경험 (3)
      • AWS re:Invent 2024 (3)

블로그 메뉴

    공지사항

    인기 글

    태그

    • Lazy Loading
    • Spring Boot Embedded Tomcat
    • 디자인패턴 #SOLID 원칙
    • jar
    • querydsl
    • war
    • 지연로딩
    • jpa

    최근 댓글

    최근 글

    갓생사는 김초원의 개발 블로그

    chocho_log

    코딩 테스트/백준

    [백준][Gold1] 구간 합 구하기 - JAVA

    2021. 4. 13. 00:34

    [문제]

    www.acmicpc.net/problem/2042

     

    2042번: 구간 합 구하기

    첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 합을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄

    www.acmicpc.net

     

    세그먼트 트리 자료구조를 이용해야 한다. 

    세그먼트 트리는 구간들을 보존하고 있는 트리로 구간합, 구간 곱 등을 구할 때 사용할 수 있다. 

    [code]

    package com.algorithm.baekjoon.gold;
    
    import java.io.*;
    import java.util.StringTokenizer;
    
    public class Test03 {
        // 세그먼트 트리를 만들 내부 클래스
        static class SegmentTree {
            long tree[];
            int treeSize;
    
            public SegmentTree(int arrSize) {
                // 트리의 높이
                int h = (int) Math.ceil(Math.log(arrSize) / Math.log(2));
    
                // 트리에 들어가는 노드의 개수
                this.treeSize = (int) Math.pow(2, h + 1);
                tree = new long[treeSize];
            }
    
            // 최초 세그먼트 그리 구성하기
            public long init(long[] nums, int node_idx, int start, int end) {
                // start==end는 리프노드라는 의미
                // 즉, 배열의 값을 그대로 저장함
                if (start == end) {
                    return tree[node_idx] = nums[start];
                }
    
                // 위에서 return 못했다면 start!=end
                // 그렇다면 좌측노드와 우축노드의 합으로 구해짐
                // 좌측노드는 *2, 우측노드는 *2+1
                return tree[node_idx] = init(nums, node_idx * 2, start, (start + end) / 2)
                        + init(nums, node_idx * 2 + 1, (start + end) / 2 + 1, end);
            }
    
            public void update(int node_idx, int start, int end, int idx, long diff) {
                // 만약 변경할 idx값이 범위 밖이면 해당트리는 확인 불필요
                if (idx < start || idx > end) return;
    
                // 변경된 차이만큼 영향받는 노드에 더해줌.
                tree[node_idx] += diff;
    
                // 리프노드에 다다르기까지 모든 노드의 값을 바꿔야하므로 지속 진행
                if (start != end) {
                    update(node_idx * 2, start, (start + end) / 2, idx, diff);
                    update(node_idx * 2 + 1, (start + end) / 2 + 1, end, idx, diff);
                }
            }
    
            public long sum(int node_idx, int start, int end, int left, int right) {
                // 범위를 벗어나게 되는 경우 더할 필요 없음
                if (left > end || right < start) {
                    return 0;
                }
    
                // 범위내 완전히 포함시에는 더 내려가지 않고 바로 리턴
                if (left <= start && end <= right) {
                    return tree[node_idx];
                }
    
                // 그 외의 경우 좌/우측으로 지속 탐색 진행
                return sum(node_idx * 2, start, (start + end) / 2, left, right) +
                        sum(node_idx * 2 + 1, (start + end) / 2 + 1, end, left, right);
            }
        }
    
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    
            StringTokenizer st = new StringTokenizer(br.readLine());
            int N = Integer.parseInt(st.nextToken());
            long updateNum = Long.parseLong(st.nextToken());
            long sumNum = Long.parseLong(st.nextToken());
    
            int count = 0;
            while ((N + count) % 4 > 0) {
                count++;
            }
    
            long[] nums = new long[N + count + 1];
            for (int i = 1; i <= N; i++) {
                nums[i] = Long.parseLong(br.readLine());
            }
    
            SegmentTree segmentTree = new SegmentTree(nums.length - 1);
            segmentTree.init(nums, 1, 1, nums.length - 1);
    
            for (int i = 0; i < updateNum + sumNum; i++) {
                st = new StringTokenizer(br.readLine());
                int type = Integer.parseInt(st.nextToken());
    
                if (type==1) {
                    int num1 = Integer.parseInt(st.nextToken());
                    long num2 = Long.parseLong(st.nextToken());
                    long diff = num2 - nums[num1];
                    nums[num1] = num2;
                    segmentTree.update(1, 1, nums.length - 1, num1, diff);
                }else if (type==2) {
                    int num3 = Integer.parseInt(st.nextToken());
                    int num4 = Integer.parseInt(st.nextToken());
                    long sum = segmentTree.sum(1, 1, nums.length - 1, num3, num4);
                    bw.write(sum+"\n");
                }else {
                    return;
                }
            }
            br.close();
            bw.flush();
            bw.close();
        }
    }
    

    '코딩 테스트 > 백준' 카테고리의 다른 글

    [백준][gold5] 14502번: 연구소 - JAVA  (0) 2021.05.08
    [백준][Gold1]11401-이항계수3-JAVA  (0) 2021.04.27
    [백준][Gold1] 책 페이지 - JAVA  (0) 2021.04.10
    [백준][Gold1] 제곱ㄴㄴ수 - JAVA  (0) 2021.04.07
    [백준][silver5][JAVA] 1010-다리 놓기  (0) 2021.03.30
      '코딩 테스트/백준' 카테고리의 다른 글
      • [백준][gold5] 14502번: 연구소 - JAVA
      • [백준][Gold1]11401-이항계수3-JAVA
      • [백준][Gold1] 책 페이지 - JAVA
      • [백준][Gold1] 제곱ㄴㄴ수 - JAVA
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그
      갓생사는 김초원의 개발 블로그 github: https://github.com/kimchowon

      티스토리툴바