PS

BOJ 2042 - 구간 합 구하기

728x90

https://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

 

세그먼트 트리를 이용한 문제.

 

세그먼트 트리는 배열 같이 연속적인 데이터가 주어졌을 때, 일부 구간 마다의 합을 구해서 트리로 표현하는 자료구조다.

 

http://arkainoh.blogspot.com/2018/06/segment.tree.html

 

[Algorithm] 세그먼트 트리 (Segment Tree)

세그먼트 트리(Segment Tree)는 배열처럼 데이터가 일렬로 나열되어 있을 때, 특정 구간의 합, 또는 특정 구간에서 가장 큰 수 등 구간의 정보를 효율적으로 얻어내기 위해 설계된 자료구조이다. 세�

arkainoh.blogspot.com

 

원래 세그먼트 트리에 대해서

그림도 직접 그리고 설명도 다 쓰려고 했지만,

그럴때마다 글 하나하나 포스팅 하는게 시간이 너무 오래걸려서

아주 잘 설명되어 있는 위 블로그 글을 참조하는게 빠른것 같다.

 

이 문제를 풀때, 재귀 방식인 Top-Down Approach 로 문제를 풀었다.

 

- c++

#include <iostream>
 
typedef long long ll;
using namespace std;
 
int N, M, K;  // N 은 총 입력될 수의 갯수, M 은 변경이 일어나는 횟수, K 는 구간의 합을 구하는 횟수 이다.
 
// 구간 합 트리 초기화 함수
ll build_tree(ll* arr, ll* tree, ll node, ll start, ll end) {
    if (start == endreturn tree[node] = arr[start];
 
    ll mid = (start + end/ 2;
    return tree[node] = build_tree(arr, tree, node * 2, start, mid) + build_tree(arr, tree, node * 2 + 1, mid + 1end);
}
 
// 구간 합 트리 데이터 수정 함수
void update(ll* tree, ll node, ll start, ll end, ll index, ll data) {
    if (index > end || index < start) return;
 
    tree[node] += data;
 
    if (start == endreturn;
 
    ll mid = (start + end/ 2;
    update(tree, node * 2, start, mid, index, data);
    update(tree, node * 2 + 1, mid + 1end, index, data);
}
 
// 구간 합 트리 데이터 조회 함수
ll query(ll* tree, ll node, ll start, ll end, ll L, ll R) {
    if (L <= start && R >= end)
        return tree[node];
    else if (R < start || L > end)
        return 0;
    else {
        ll mid = (start + end/ 2;
        return query(tree, node * 2, start, mid, L, R) + query(tree, node * 2 + 1, mid + 1end, L, R);
    }
}
 
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
 
    cin >> N >> M >> K;
 
    ll* arr = new ll[N];
    ll* tree = new ll[4 * N];
 
    arr[0= 0;
    tree[0= 0;
 
    for (int i = 1; i <= N; i++) {
        cin >> arr[i];
    }
 
    build_tree(arr, tree, 11, N);
 
    ll a, b, c;
    for (int i = 0; i < M + K; i++) {
        cin >> a >> b >> c;
        if (a == 1) {
            // update 함수를 수행
            ll data = c - arr[b];
            update(tree, 11, N, b, data);
            arr[b] += data;
        } else if (a == 2) {
            // query 함수를 수행
            cout << query(tree, 11, N, b, c) << '\n';
        }
    }
 
    //delete[] tree;
    //delete[] arr;
    return 0;
}
cs

 

 

 

왜 저런지는 아직도 잘 모르겠지만

동적할당을 해제하는 delete[] 구문을 사용하면 런타임 에러가 뜬다.

 

 

확실히 solved.ac 기준 플레티넘 이상의 문제들은

개념 이해하는데만 꽤 오랜 시간이 걸린것같다.

이문제도 그렇고..

728x90

'PS' 카테고리의 다른 글

BOJ 1157 - 단어 공부  (0) 2020.08.13
BOJ 2231 - 분해합  (0) 2020.08.12
BOJ 2309 - 일곱 난쟁이  (0) 2020.08.11
BOJ 1002 - 터렛  (0) 2020.08.07
BOJ 1759 - 암호 만들기  (0) 2020.08.05