본문 바로가기
공부/C++

[C++] Sqrt Decomposition 알고리즘

by 기찬이즘 2024. 6. 28.
반응형

 

Sqrt Decomposition 알고리즘은 연속된 어떤 배열을 구간 별로 합을 bucket에 저장하여 효과적으로 구간합을 구할 수 있는 알고리즘이다. 주로 어디서 부터 어디까지 합을 구해야하는 문제에서 요긴하게 쓸 수 있다. 시간복잡도는 O( n)으로, 보다 빠른 방법은 Segment tree 알고리즘이 있지만, Sqrt Decomposition이 상대적으로 구현하기 쉽고 Segment tree로 풀 수 없는 문제도 풀 수 있으니 꼭 알아두자.

 

예제로 백준 2042번: 구간 합 구하기를 풀어보자.

#include <iostream>
#include <math.h>
#define MAX 1'000'001
using namespace std;
typedef long long ll;
ll N, M, K;
ll Numbers[MAX];
ll Bucket[MAX];

int main() {
    cin >> N >> M >> K;
    ll sqrtNum = sqrt(N);

    for (int i = 0; i < N; ++i) {
        cin >> Numbers[i];
        Bucket[i / sqrtNum] += Numbers[i];
    }

    for (int i = 0; i < M + K; ++i) {
        ll a, b, c;
        cin >> a >> b >> c;

        if (a == 1) {
            b--;
            Bucket[b / sqrtNum] -= Numbers[b];
            Bucket[b / sqrtNum] += c;
            Numbers[b] = c;
        }
        else if (a == 2) {
            ll sum = 0;
            b--;
            c--;
            /* left & right */
            while (b % sqrtNum != 0 && b <= c) {
                sum += Numbers[b++];
            }
            while ((c+1) % sqrtNum != 0 && b <= c) {
                sum += Numbers[c--];
            }

            /* bucket */
            while (b <= c) {
                sum += Bucket[b / sqrtNum];
                b += sqrtNum;
            }

            cout << sum << "\n";
        }
    }
}

구간합을 구하는 문제는 주로 범위가 매우 크니, 자료형이 범위에 들어오는지 잘 체크하자.

위 코드를 통해 제출하면 Segment tree 방법에 비해 4배 정도 느리지만 통과하는 것을 확인할 수 있다.

 

반응형