본문 바로가기
문제풀이

백준 2042 구간합 JAVA

by AndoneKwon 2020. 12. 22.

인풋이 워낙 크다보니 단순한 반복으론 못푸는 문제이다.
구간합을 세그먼트 트리를 이용하여 저장하는 방식이다.
세그먼트 트리는 이진 탐색을 이용해 사전에 트리에 구간의 합을 저장해 놓고
그 구간의 합을 재활용 하는 식으로 구현이 된다.

자세한 구현 방법은 다음 문제에서 자세히 설명하도록 하겠다.

package com.company;
import java.io.*;
import java.util.*;

//아래 함수에서 start는 구간의 시작을 의미. end는 구간의 끝을 의미.
class SegTree{
    long arr[];
    long tree[];

    SegTree(long[] arr){
        this.arr=arr;
        this.tree=new long[arr.length*4];
    }

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

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

    public void update(int start, int end,int node,int index, long changNum){
        if(start>index||end<index)
            return;
        tree[node]+=changNum;//바꾸고자하는 인덱스의 요소와
        if(start!=end){
            int mid=(start+end)/2;
            update(start,mid,node*2,index,changNum);
            update(mid+1,end,node*2+1,index,changNum);
        }
    }
}

public class Main {
    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;

        st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int K = Integer.parseInt(st.nextToken());
        long[] arr = new long[N];

        for(int i=0;i<N;i++){
            arr[i]=Long.parseLong(br.readLine());
        }

        SegTree tree = new SegTree(arr);
        tree.init(0,N-1,1);

        for(int i=0;i<M+K;i++){
            st=new StringTokenizer(br.readLine());
            int operator = Integer.parseInt(st.nextToken());
            if(operator==1){
                int index = Integer.parseInt(st.nextToken());
                long changeNum = Integer.parseInt(st.nextToken());
                tree.update(0,N-1,1,index-1,changeNum-tree.arr[index-1]);
                tree.arr[index-1]=changeNum;
            }else if(operator==2){
                int left = Integer.parseInt(st.nextToken());
                int right = Integer.parseInt(st.nextToken());
                bw.write(Long.toString(tree.sum(0,N-1,1,left-1,right-1)));
                bw.newLine();
            }
        }

        bw.flush();
        bw.close();
    }
}

'문제풀이' 카테고리의 다른 글

Leetcode Pascal's Triangle II JAVA  (0) 2020.12.24
Leetcode Merge Two Sorted Lists  (0) 2020.12.23
백준 11559번 Puyo Puyo JAVA  (0) 2020.12.02
백준 14503번 로봇청소기 JAVA  (0) 2020.12.01
백준 1717번 집합의 표현 JAVA  (0) 2020.11.30