BOJ 11505

구간 곱 구하기

문제출처

문제 해석

  • N개의 배열이 주어지고 몇개의 인덱스의 수가 수정이 이루어졌을 때, 구간 곱을 구하는 문제입니다.

설계(10)

  • 세그먼트트리의 응용문제입니다.
  • 이전까지는 구간합을 구하는 문제였지만, 해당문제는 합하는 것을 곱하는 것으로 바꾼 문제입니다.
  • 세그트리를 만들 때, 각 수의 곱을 하고 MOD를 취해줍니다.
  • update를 하는 부분에서 이전과 다른 점은 바꿀 수와 현재 수의 diff값으로 더해주는 방식이 아닌, 값 자체를 계속 곱해나가는 식으로 바꿔주면 됩니다.
  • 구간곱을 구하는 과정에서는 범위 자체를 벗어나는 경우 1을 리턴해줘야 한다는 점만 조심하면 될 것 같습니다.

구현(30)

코드
#include <iostream>
#include <vector>
using namespace std;
#define MAXN 1000001
#define MOD 1000000007
typedef long long ll;

int arr[MAXN];

vector<ll> tree;
int N,M,K;

ll init(int node, int start, int end){
    if (start == end) return tree[node] = arr[start];
    int mid = (start+end)/2;
    return tree[node] = ((init(node*2,start,mid)%MOD)*(init(node*2+1,mid+1, end)%MOD))%MOD;
}
ll update(int node, int start, int end, int idx, ll val){
    if (!(start <= idx && idx <= end)){
        return tree[node];
    }
    if (start == end) return tree[node] = val;
    int mid = (start + end) / 2;
    return tree[node] = (update(node*2,start,mid,idx,val)*update(node*2+1,mid+1,end,idx,val))%MOD;
}

ll mul(int node, int start, int end, int left, int right){
    if (left > end || right < start) return 1;

    if (left <= start && end <= right) return tree[node];
    int mid = (start + end) / 2;
    return (mul(node*2,start,mid,left,right)*mul(node*2+1,mid+1,end,left,right))%MOD;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N >> M >> K;
    M += K;
    for (int i = 0; i<N;i++){
        cin >> arr[i];
    }
    int h = 1;
    while (h < N) h<<=1;
    tree = vector<ll> (h*2);
    init(1,0,N-1);
    while (M--){
        int a;
        cin >> a;
        if (a == 1){
            int idx;
            ll val;
            cin >> idx >> val;
            update(1,0,N-1,idx-1,val);
        }
        else{
            int left,right;
            cin >> left >> right;
            cout << mul(1,0,N-1,left-1,right-1)%MOD <<"\n";
        }
    }
    return 0;
}
디버깅
  • init을 하는 과정에서 start==end일 때 tree에 저장을 하지 않는 실수를 하여 디버깅을 통해 수정하였습니다.
제출결과
  • 136ms

마무리

  • 세그먼트트리를 이용한 구간곱을 구하는 문제였습니다. 이전과 별 다를 바 없는 문제로 기본을 알면 풀 수 있을 것입니다.