접근

https://www.acmicpc.net/problem/11505

 

11505번: 구간 곱 구하기

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

www.acmicpc.net

세그먼트 트리를 이용하여 답을 구할 수 있다. 세그먼트 트리란 구간 합을 빠르게 구할 때 자주 사용하는 알고리즘으로써 예를 들어 10개의 요소가 있다면 1번 노드에 1~10 까지의 합을 계산해두고, 그 자식 노드인 2, 3번 노드에 각각 0~5, 6~10 까지의 합을 계산해둔다. 이를 반복하여 트리의 맨 아래까지 모두 계산해두면, 구간의 합을 구할 때 시간을 매우 단축시킬 수 있다.

처음에 주어진 숫자들을 가지고 세그먼트 트리를 구성하는 Init 함수, 주어진 구간에서의 곱을 구하는 Multiply 함수, index 번째 수를 new_num으로 바꾸는 Update 함수 세가지로 구성된다.

코드

#include <algorithm>
#include <iostream>

using namespace std;

#define endl '\n'
#define MAX_N 1000002
#define MOD 1000000007

int N, M, K;
int NUM[MAX_N];
long long int SegmentTree[MAX_N * 4];

// NUM 배열에 저장된 정보를 가지고 세그먼트 트리를 초기화하는 함수
long long int Init(int start, int end, int node) {
    if (start == end) return SegmentTree[node] = NUM[start];
    int mid = (start + end) / 2;
    return (SegmentTree[node] = (Init(start, mid, node * 2) * Init(mid + 1, end, node * 2 + 1)) % MOD);
}

// left~right 까지 구간의 곱을 구하는 함수
long long int Multiply(int start, int end, int node, int left, int right) {
    if (end < left || right < start) return 1;
    if (left <= start && end <= right) return SegmentTree[node];
    int mid = (start + end) / 2;
    return ((Multiply(start, mid, node * 2, left, right) * Multiply(mid + 1, end, node * 2 + 1, left, right)) % MOD);
}

// index 번째 수를 new_num으로 바꾸는 함수
long long int Update(int start, int end, int node, int index, int new_num) {
    if (index < start || end < index) return SegmentTree[node];
    if (start == end) return SegmentTree[node] = new_num;
    int mid = (start + end) / 2;
    return SegmentTree[node] = (Update(start, mid, node * 2, index, new_num) * Update(mid + 1, end, node * 2 + 1, index, new_num)) % MOD;
}

int main(int argc, char** argv) {
    // freopen 주석 처리
    freopen("input.txt", "r", stdin);

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin >> N >> M >> K;
    for (int i = 1; i <= N; i++) {
        cin >> NUM[i];
    }
    Init(1, N, 1);
    int a, b, c;
    for (int i = 0; i < M + K; i++) {
        cin >> a >> b >> c;
        if (a == 1) {
            Update(1, N, 1, b, c);
        } else {
            cout << Multiply(1, N, 1, min(b, c), max(b, c)) << endl;
        }
    }

    return 0;
}

더 생각해 볼 것?

...

코드나 내용 관련 조언, 부족한 점 및 질문 언제든 환영합니다!

반응형

'코딩 > 백준 (C++)' 카테고리의 다른 글

백준 1708번 : 볼록 껍질 (C++)  (0) 2022.05.20
백준 11658번: 구간 합 구하기 3 (C++)  (0) 2022.05.19
백준 11281번: 2-SAT - 4 (C++)  (0) 2022.05.19
백준 11280번: 2-SAT - 3 (C++)  (0) 2022.05.18
백준 4013번: ATM (C++)  (0) 2022.05.18
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기