본문 바로가기

BAEKJOON/자료 구조

백준 12837번 [가계부 (Hard)](C++)-yes6686- 티스토리

728x90
SMALL

백준 문제 풀이: 12837 [가계부 (Hard)]


문제 링크: https://www.acmicpc.net/problem/12837

문제 설명:

1부터 N까지 번호가 매겨진 계좌의 금액을 관리하며, 다음 두 가지 작업을 효율적으로 수행하는 문제입니다:

  • 타겟 계좌에 금액 추가
  • 특정 구간의 계좌 합을 계산

각 작업에 대해 효율적인 시간 복잡도를 유지해야 하므로 세그먼트 트리를 사용합니다.


문제 해결 코드


#include <iostream>
using namespace std;

long long int arr[1000001];
long long int t[4000001];

long long int sum(int n, int s, int e, int l, int r) {
    if (r < s || l > e) return 0;
    if (l <= s && e <= r) return t[n];

    return sum(n * 2, s, (s + e) / 2, l, r) + sum(n * 2 + 1, (s + e) / 2 + 1, e, l, r);
}

void modify(int n, int s, int e, int i, long long int diff) {
    if (i < s || e < i) return;
    t[n] += diff;
    if (s != e) {
        modify(2 * n, s, (s + e) / 2, i, diff);
        modify(2 * n + 1, (s + e) / 2 + 1, e, i, diff);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int n, m;
    cin >> n >> m;
    long long int a, b, c;
    for (int i = 0; i < m; i++) {
        cin >> a >> b >> c;
        if (a == 2) { 
            cout << sum(1, 0, n - 1, b - 1, c - 1) << '\n';
        } else if (a == 1) { 
            long long int d = c;
            arr[b - 1] += c;
            modify(1, 0, n - 1, b - 1, d);
        }
    }
    return 0;
}

코드 설명

  • 핵심 알고리즘: 세그먼트 트리를 활용하여 구간 합을 계산하고, 특정 계좌의 금액을 추가할 수 있도록 구현합니다.
  • 구현 세부사항:
    • sum: 특정 구간의 합을 계산하는 함수입니다. 구간이 겹치는 노드만 계산하여 효율적으로 구간 합을 반환합니다.
    • modify: 특정 계좌에 금액을 추가하고, 이를 반영하기 위해 세그먼트 트리를 갱신합니다.
    • t: 세그먼트 트리를 저장하는 배열입니다.
  • 시간 복잡도: O(log n) (각 쿼리에 대해)
    • 구간 합 계산: O(log n)
    • 값 갱신: O(log n)

결과

입력된 작업에 따라 특정 계좌에 금액을 추가하거나, 주어진 구간의 합을 효율적으로 계산합니다. 세그먼트 트리를 사용하여 대규모 입력에서도 빠르게 동작합니다.

다른 접근 방식이나 개선 사항이 있다면 댓글로 공유 부탁드립니다!

728x90
LIST